mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
bugfixes + tonlib update
This commit is contained in:
parent
2f81361a02
commit
eecf05ca59
35 changed files with 734 additions and 193 deletions
|
@ -15,6 +15,11 @@
|
|||
|
||||
<b b> constant empty_cell
|
||||
|
||||
variable @default-subwallet-id
|
||||
@default-subwallet-id 0!
|
||||
{ @default-subwallet-id @ } : default-subwallet-id
|
||||
{ @default-subwallet-id ! } : default-subwallet-id!
|
||||
|
||||
// b x --> b' ( serializes a Gram amount )
|
||||
{ -1 { 1+ 2dup 8 * ufits } until
|
||||
rot over 4 u, -rot 8 * u, } : Gram,
|
||||
|
@ -228,9 +233,37 @@ variable special-dict
|
|||
|
||||
|
||||
// restricted wallet creation
|
||||
|
||||
// same as in new-wallet-v3.fif
|
||||
<{ SETCP0 DUP IFNOTRET // return if recv_internal
|
||||
DUP 85143 INT EQUAL OVER 78748 INT EQUAL OR IFJMP:<{ // "seqno" and "get_public_key" get-methods
|
||||
1 INT AND c4 PUSHCTR CTOS 32 LDU 32 LDU NIP 256 PLDU CONDSEL // cnt or pubk
|
||||
}>
|
||||
INC 32 THROWIF // fail unless recv_external
|
||||
9 PUSHPOW2 LDSLICEX DUP 32 LDU 32 LDU 32 LDU // signature in_msg subwallet_id valid_until msg_seqno cs
|
||||
NOW s1 s3 XCHG LEQ 35 THROWIF // signature in_msg subwallet_id cs msg_seqno
|
||||
c4 PUSH CTOS 32 LDU 32 LDU 256 LDU ENDS // signature in_msg subwallet_id cs msg_seqno stored_seqno stored_subwallet public_key
|
||||
s3 s2 XCPU EQUAL 33 THROWIFNOT // signature in_msg subwallet_id cs public_key stored_seqno stored_subwallet
|
||||
s4 s4 XCPU EQUAL 34 THROWIFNOT // signature in_msg stored_subwallet cs public_key stored_seqno
|
||||
s0 s4 XCHG HASHSU // signature stored_seqno stored_subwallet cs public_key msg_hash
|
||||
s0 s5 s5 XC2PU // public_key stored_seqno stored_subwallet cs msg_hash signature public_key
|
||||
CHKSIGNU 35 THROWIFNOT // public_key stored_seqno stored_subwallet cs
|
||||
ACCEPT
|
||||
WHILE:<{
|
||||
DUP SREFS // public_key stored_seqno stored_subwallet cs _51
|
||||
}>DO<{ // public_key stored_seqno stored_subwallet cs
|
||||
8 LDU LDREF s0 s2 XCHG // public_key stored_seqno stored_subwallet cs _56 mode
|
||||
SENDRAWMSG
|
||||
}> // public_key stored_seqno stored_subwallet cs
|
||||
ENDS SWAP INC // public_key stored_subwallet seqno'
|
||||
NEWC 32 STU 32 STU 256 STU ENDC c4 POP
|
||||
}>c
|
||||
=: WCode3
|
||||
|
||||
"auto/wallet-code.fif" include =: WCode0
|
||||
"auto/restricted-wallet-code.fif" include =: RWCode1
|
||||
"auto/restricted-wallet2-code.fif" include =: RWCode2
|
||||
"auto/restricted-wallet3-code.fif" include =: RWCode3
|
||||
|
||||
// pubkey amount --
|
||||
{ over ."Key " pubkey>$ type ." -> "
|
||||
|
@ -245,10 +278,21 @@ variable special-dict
|
|||
Masterchain swap 6 .Addr cr
|
||||
} : create-wallet1
|
||||
|
||||
// pubkey amount
|
||||
{ over ."W0 Key " pubkey>$ type space dup .GR ." -> "
|
||||
WCode3 // code
|
||||
<b 0 32 u, default-subwallet-id 32 u, 3 roll 256 u, b> // data
|
||||
empty_cell // libs
|
||||
3 roll // balance
|
||||
0 0 2 register_smc
|
||||
Masterchain swap 6 .Addr cr
|
||||
} : create-wallet0
|
||||
|
||||
// D x t -- D'
|
||||
{ <b rot Gram, swap rot 32 b>idict! not abort"cannot add value"
|
||||
} : rdict-entry
|
||||
{ 86400 * } : days*
|
||||
{ 365 * days* } : years*
|
||||
// balance -- dict
|
||||
{ dictnew
|
||||
over 31 -1<< rdict-entry
|
||||
|
@ -256,14 +300,27 @@ variable special-dict
|
|||
over 1/2 */ 183 days* rdict-entry
|
||||
swap 1/4 */ 365 days* rdict-entry
|
||||
0 548 days* rdict-entry
|
||||
} : make-rdict
|
||||
} : make-rdict1
|
||||
{ dictnew
|
||||
over 31 -1<< rdict-entry
|
||||
over .9 */ 0 rdict-entry
|
||||
over .6775 */ 1 years* rdict-entry
|
||||
over .445 */ 2 years* rdict-entry
|
||||
swap .2225 */ 3 years* rdict-entry
|
||||
0 4 years* 86400 + rdict-entry
|
||||
} : make-rdict2
|
||||
|
||||
variable 'make-rdict
|
||||
{ 'make-rdict @ execute } : make-rdict
|
||||
|
||||
variable rwallet-start-at rwallet-start-at 0!
|
||||
now 86400 / 1+ 86400 * rwallet-start-at !
|
||||
|
||||
variable wallet2-start-at wallet2-start-at 0!
|
||||
now 86400 / 1+ 86400 * wallet2-start-at !
|
||||
// pubkey amount --
|
||||
{ over ."Key " pubkey>$ type ." -> "
|
||||
RWCode2 // code
|
||||
<b 1 32 u, 3 pick 256 u, 3 roll wallet2-start-at @ 32 u, make-rdict dict, b> // data
|
||||
<b 1 32 u, 3 pick 256 u, rwallet-start-at @ 32 u,
|
||||
3 roll make-rdict dict, b> // data
|
||||
empty_cell // libs
|
||||
3 roll // balance
|
||||
0 // split_depth
|
||||
|
@ -273,8 +330,42 @@ now 86400 / 1+ 86400 * wallet2-start-at !
|
|||
Masterchain swap 6 .Addr cr
|
||||
} : create-wallet2
|
||||
|
||||
variable rwallet-init-pubkey
|
||||
|
||||
// pubkey -- addr
|
||||
{ RWCode3 // code
|
||||
<b 0 32 u, default-subwallet-id 32 u,
|
||||
rwallet-init-pubkey @ 256 u,
|
||||
rot 256 u,
|
||||
b> // data
|
||||
empty_cell // libs
|
||||
0 // balance
|
||||
0 0 0 register_smc // compute address only
|
||||
} : precompute-wallet3-addr
|
||||
|
||||
variable w3-addr
|
||||
|
||||
// pubkey amount 'rdict --
|
||||
{ 'make-rdict ! over precompute-wallet3-addr w3-addr !
|
||||
over ."RW3 Key " pubkey>$ type space dup .GR ." -> "
|
||||
RWCode3 // code
|
||||
<b 1 32 u, default-subwallet-id 32 u, 3 roll 256 u, rwallet-start-at @ 32 u,
|
||||
2 pick make-rdict dict, b> // data
|
||||
empty_cell // libs
|
||||
3 roll // balance
|
||||
0 // split_depth
|
||||
0 // ticktock
|
||||
w3-addr @ // address
|
||||
6 // mode: create+setaddr
|
||||
register_smc
|
||||
Masterchain swap 6 .Addr cr
|
||||
} : create-wallet3-internal
|
||||
|
||||
{ ' make-rdict1 create-wallet3-internal } : create-wallet3
|
||||
{ ' make-rdict2 create-wallet3-internal } : create-wallet3b
|
||||
|
||||
// pubkey amount
|
||||
{ over ."Key " pubkey>$ type ." -> "
|
||||
{ over ."Key " pubkey>$ type space dup .GR ." -> "
|
||||
WCode0 // code
|
||||
<b 1 32 u, 3 roll 256 u, b> // data
|
||||
empty_cell // libs
|
||||
|
@ -284,7 +375,7 @@ now 86400 / 1+ 86400 * wallet2-start-at !
|
|||
2 // mode: create
|
||||
register_smc
|
||||
Masterchain swap 6 .Addr cr
|
||||
} : create-wallet0
|
||||
} : create-wallet0a
|
||||
|
||||
{ dup tlb-type-lookup { nip } { "unknown TLB type " swap $+ abort } cond } : $>tlb
|
||||
{ bl word $>tlb 1 'nop } ::_ tlb:
|
||||
|
|
110
crypto/smartcont/new-restricted-wallet3.fif
Normal file
110
crypto/smartcont/new-restricted-wallet3.fif
Normal file
|
@ -0,0 +1,110 @@
|
|||
#!/usr/bin/fift -s
|
||||
"TonUtil.fif" include
|
||||
"Asm.fif" include
|
||||
"GetOpt.fif" include
|
||||
|
||||
{ show-options-help 1 halt } : usage
|
||||
0 =: restrict-mode
|
||||
-1 =: wc
|
||||
null =: subwallet-id
|
||||
86400 =: expires-in
|
||||
now =: start-at
|
||||
0x5EA62080 =: start-at
|
||||
0x4BA92D8A =: subwallet-base
|
||||
|
||||
begin-options
|
||||
" <creator-filename-base> <public-key> <amount> [-w<workchain>][-r<restrict-mode>][-i<subwallet-id>][-t<start-at>] [<savefile>]" +cr +tab
|
||||
+"Creates a restricted lockup wallet v3 in the masterchain initialized by key loaded from <init-filename-base> "
|
||||
+"and controlled by the private key corresponding to <public-key>" +cr +tab
|
||||
+"and saves its initialization query into new-<savefile>.boc and its address into <savefile>.addr ('rwallet.addr' by default)"
|
||||
disable-digit-options generic-help-setopt
|
||||
"r" "--restrict-mode" { parse-int =: restrict-mode } short-long-option-arg
|
||||
"Selects a standard restriction mode: 1 for 18-month lockup, 2 for 4-year lockup" option-help
|
||||
"w" "--workchain" { parse-int =: wc } short-long-option-arg
|
||||
"Selects a workchain (" wc (.) $+ +" by default)" option-help
|
||||
"i" "--subwallet-id" { parse-int =: subwallet-id } short-long-option-arg
|
||||
"Sets 32-bit subwallet id (workchain plus " subwallet-base (.) $+ +" by default)" option-help
|
||||
"x" "--expires-in" { parse-int =: expires-in } short-long-option-arg
|
||||
"Expiration time of the initialization message (" expires-in (.) $+
|
||||
+" seconds by default)" option-help
|
||||
"t" "--start-at" { parse-int =: start-at } short-long-option-arg
|
||||
"Restriction start Unixtime (now by default)" option-help
|
||||
"h" "--help" { usage } short-long-option
|
||||
"Shows a help message" option-help
|
||||
parse-options
|
||||
|
||||
$# dup 3 < swap 4 > or ' usage if
|
||||
4 :$1..n
|
||||
|
||||
$1 =: filename-base
|
||||
$2 parse-pubkey =: PubKey
|
||||
$3 $>GR =: amount
|
||||
$4 "rwallet" replace-if-null =: savefile-base
|
||||
subwallet-id subwallet-base wc + replace-if-null =: subwallet-id
|
||||
expires-in now + =: expires-at
|
||||
|
||||
"new-" savefile-base $+ +".boc" =: savefile
|
||||
savefile-base +".addr" =: savefile-addr
|
||||
|
||||
wc 8 fits not abort"invalid workchain id"
|
||||
subwallet-id 32 fits not abort"invalid subwallet-id"
|
||||
expires-at 32 ufits not abort"invalid expiration time"
|
||||
start-at 32 ufits not abort"invalid restriction start time"
|
||||
restrict-mode dup 1 < swap 2 > or abort"unknown restriction mode"
|
||||
filename-base +".pk" load-keypair =: init_pk =: init_pubkey
|
||||
|
||||
."Creating new restricted lockup wallet v3 in workchain " wc .
|
||||
."with restriction mode " restrict-mode . ."and nominal amount " amount .GR cr
|
||||
."controlled by public key " PubKey .pubkey ." and initialized by public key " init_pubkey 256 B>u@ .pubkey cr
|
||||
."(subwallet id is " subwallet-id ._ .")" cr
|
||||
|
||||
// D x t -- D'
|
||||
{ <b rot Gram, swap rot 32 b>idict! not abort"cannot add value"
|
||||
} : rdict-entry
|
||||
{ 86400 * } : days*
|
||||
{ 365 * days* } : years*
|
||||
// balance -- dict
|
||||
{ dictnew
|
||||
over 31 -1<< rdict-entry
|
||||
over 3/4 */ 91 days* rdict-entry
|
||||
over 1/2 */ 183 days* rdict-entry
|
||||
swap 1/4 */ 365 days* rdict-entry
|
||||
0 548 days* rdict-entry
|
||||
} : make-rdict1
|
||||
{ dictnew
|
||||
over 31 -1<< rdict-entry
|
||||
over .9 */ 0 rdict-entry
|
||||
over .6775 */ 1 years* rdict-entry
|
||||
over .445 */ 2 years* rdict-entry
|
||||
swap .2225 */ 3 years* rdict-entry
|
||||
0 4 years* 86400 + rdict-entry
|
||||
} : make-rdict2
|
||||
|
||||
amount
|
||||
restrict-mode 1 = { make-rdict1 } { make-rdict2 } cond =: rdict
|
||||
|
||||
."Restrictions start at " start-at ._ .": " cr
|
||||
rdict 32 { swap . ."-> " Gram@ .GR cr true } idictforeach cr
|
||||
|
||||
// Create new restricted wallet v3; code taken from `auto/restricted-wallet3-code.fif`
|
||||
"auto/restricted-wallet3-code.fif" include // code
|
||||
<b 0 32 u, subwallet-id 32 i, init_pubkey B, PubKey 256 u, b> // data
|
||||
null // no libraries
|
||||
<b b{0011} s, 3 roll ref, rot ref, swap dict, b> // create StateInit
|
||||
dup ."StateInit: " <s csr. cr
|
||||
dup =: StateInit hashu wc swap 2dup 2constant wallet_addr
|
||||
."new wallet address = " 2dup .addr cr
|
||||
2dup savefile-addr save-address-verbose
|
||||
."Non-bounceable address (for init): " 2dup 7 .Addr cr
|
||||
."Bounceable address (for later access): " 6 .Addr cr
|
||||
|
||||
<b subwallet-id 32 u, expires-at 32 u, 0 32 u, start-at 32 u, rdict dict, b>
|
||||
dup ."signing message: " <s csr. cr
|
||||
dup hashu init_pk ed25519_sign_uint
|
||||
|
||||
<b b{1000100} s, wallet_addr addr, b{000010} s, StateInit <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
|
||||
savefile tuck B>file
|
||||
."(Saved wallet creating query to file " type .")" cr
|
|
@ -7,8 +7,13 @@ int err:replay_protection() asm "34 PUSHINT";
|
|||
int err:no_timeout() asm "35 PUSHINT";
|
||||
int err:expected_init() asm "36 PUSHINT";
|
||||
int err:expected_close() asm "37 PUSHINT";
|
||||
int err:expected_payout() asm "37 PUSHINT";
|
||||
int err:no_promise_signature() asm "38 PUSHINT";
|
||||
int err:wrong_channel_id() asm "39 PUSHINT";
|
||||
int err:unknown_op() asm "40 PUSHINT";
|
||||
int err:not_enough_fee() asm "41 PUSHINT";
|
||||
|
||||
int op:pchan_cmd() asm "0x912838d1 PUSHINT";
|
||||
|
||||
int msg:init() asm "0x27317822 PUSHINT";
|
||||
int msg:close() asm "0xf28ae183 PUSHINT";
|
||||
|
@ -19,6 +24,8 @@ int state:init() asm "0 PUSHINT";
|
|||
int state:close() asm "1 PUSHINT";
|
||||
int state:payout() asm "2 PUSHINT";
|
||||
|
||||
int min_fee() asm "1000000000 PUSHINT";
|
||||
|
||||
|
||||
;; A - initial balance of Alice,
|
||||
;; B - initial balance of B
|
||||
|
@ -60,7 +67,8 @@ _ unpack_config(cell config) {
|
|||
cs~load_uint(256),
|
||||
cs~load_ref().begin_parse(),
|
||||
cs~load_ref().begin_parse(),
|
||||
cs~load_uint(64));
|
||||
cs~load_uint(64),
|
||||
cs~load_grams());
|
||||
cs.end_parse();
|
||||
return res;
|
||||
}
|
||||
|
@ -164,8 +172,8 @@ cell do_payout(int promise_A, int promise_B, int A, int B, slice a_addr, slice b
|
|||
A += diff;
|
||||
B -= diff;
|
||||
|
||||
send_payout(a_addr, A, channel_id, 3);
|
||||
send_payout(b_addr, B, channel_id, 3);
|
||||
send_payout(a_addr, A, channel_id, 3 + 128);
|
||||
|
||||
return begin_cell()
|
||||
.store_int(state:payout(), 3)
|
||||
|
@ -179,7 +187,7 @@ cell do_payout(int promise_A, int promise_B, int A, int B, slice a_addr, slice b
|
|||
;; init$000 inc_A:Grams inc_B:Grams min_A:Grams min_B:Grams = Message;
|
||||
;;
|
||||
cell with_init(slice state, int msg_value, slice msg, int msg_signed_A?, int msg_signed_B?,
|
||||
slice a_addr, slice b_addr, int init_timeout, int channel_id) {
|
||||
slice a_addr, slice b_addr, int init_timeout, int channel_id, int min_A_extra) {
|
||||
;; parse state
|
||||
(int signed_A?, int signed_B?, int min_A, int min_B, int expire_at, int A, int B) = unpack_state_init(state);
|
||||
|
||||
|
@ -217,6 +225,7 @@ cell with_init(slice state, int msg_value, slice msg, int msg_signed_A?, int msg
|
|||
}
|
||||
|
||||
if (signed_A? & signed_B?) {
|
||||
A -= min_A_extra;
|
||||
if ((min_A > A) | (min_B > B)) {
|
||||
return do_payout(0, 0, A, B, a_addr, b_addr, channel_id);
|
||||
}
|
||||
|
@ -289,24 +298,57 @@ cell with_close(slice cs, slice msg, int msg_signed_A?, int msg_signed_B?, int a
|
|||
return pack_state_close(signed_A?, signed_B?, promise_A, promise_B, expire_at, A, B);
|
||||
}
|
||||
|
||||
() with_payout(slice cs, slice msg, slice a_addr, slice b_addr, int channel_id) impure {
|
||||
int op = msg~load_uint(32);
|
||||
throw_unless(err:expected_payout(), op == msg:payout());
|
||||
(int A, int B) = (cs~load_grams(), cs~load_grams());
|
||||
throw_unless(err:not_enough_fee(), A + B + 1000000000 < get_balance().pair_first());
|
||||
accept_message();
|
||||
send_payout(b_addr, B, channel_id, 3);
|
||||
send_payout(a_addr, A, channel_id, 3 + 128);
|
||||
}
|
||||
|
||||
() recv_any(int msg_value, slice msg) impure {
|
||||
if (msg.slice_empty?()) {
|
||||
return();
|
||||
}
|
||||
;; op is not signed, but we don't need it to be signed.
|
||||
int op = msg~load_uint(32);
|
||||
if (op <= 1) {
|
||||
;; simple transfer with comment, return
|
||||
;; external message will be aborted
|
||||
;; internal message will be accepted
|
||||
return ();
|
||||
}
|
||||
throw_unless(err:unknown_op(), op == op:pchan_cmd());
|
||||
|
||||
(cell config, cell state) = unpack_data();
|
||||
(int init_timeout, int close_timeout, int a_key, int b_key, slice a_addr, slice b_addr, int channel_id) = config.unpack_config();
|
||||
(int init_timeout, int close_timeout, int a_key, int b_key,
|
||||
slice a_addr, slice b_addr, int channel_id, int min_A_extra) = config.unpack_config();
|
||||
(int msg_signed_A?, int msg_signed_B?) = msg~unwrap_signatures(a_key, b_key);
|
||||
|
||||
slice cs = state.begin_parse();
|
||||
int state_type = cs~load_uint(3);
|
||||
|
||||
if (state_type == state:init()) { ;; init
|
||||
state = with_init(cs, msg_value, msg, msg_signed_A?, msg_signed_B?, a_addr, b_addr, init_timeout, channel_id);
|
||||
state = with_init(cs, msg_value, msg, msg_signed_A?, msg_signed_B?, a_addr, b_addr, init_timeout, channel_id, min_A_extra);
|
||||
} if (state_type == state:close()) {
|
||||
state = with_close(cs, msg, msg_signed_A?, msg_signed_B?, a_key, b_key, a_addr, b_addr, close_timeout, channel_id);
|
||||
} if (state_type == state:payout()) {
|
||||
with_payout(cs, msg, a_addr, b_addr, channel_id);
|
||||
}
|
||||
|
||||
pack_data(config, state);
|
||||
}
|
||||
|
||||
() recv_internal(int msg_value, cell in_msg_cell, slice in_msg) impure {
|
||||
;; TODO: uncomment when supported in tests
|
||||
;; var cs = in_msg_cell.begin_parse();
|
||||
;; var flags = cs~load_uint(4); ;; int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
|
||||
;; if (flags & 1) {
|
||||
;; ;; ignore all bounced messages
|
||||
;; return ();
|
||||
;; }
|
||||
recv_any(msg_value, in_msg);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue