mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
added support for config change proposals
- added some fift scripts for the config change proposal voting - added validator-engine-console support for the config change proposal voting - additional sanity checks in catchain - unsafe slow catchain resync method
This commit is contained in:
parent
a31f8d4424
commit
4dd5eea11f
35 changed files with 753 additions and 144 deletions
|
@ -23,18 +23,18 @@
|
|||
.end_cell());
|
||||
}
|
||||
|
||||
;; [min_tot_rounds, max_tot_rounds, min_wins, max_losses, min_store_sec, max_store_sec, bit_price, cell_price]
|
||||
;; (min_tot_rounds, max_tot_rounds, min_wins, max_losses, min_store_sec, max_store_sec, bit_price, cell_price)
|
||||
_ parse_vote_config(cell c) inline {
|
||||
var cs = c.begin_parse();
|
||||
throw_unless(44, cs~load_uint(8) == 0x36);
|
||||
var res = [cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(32), cs~load_uint(32), cs~load_uint(32), cs~load_uint(32)];
|
||||
var res = (cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(8), cs~load_uint(32), cs~load_uint(32), cs~load_uint(32), cs~load_uint(32));
|
||||
cs.end_parse();
|
||||
return res;
|
||||
}
|
||||
|
||||
;; cfg_vote_setup#91 normal_params:^ConfigProposalSetup critical_params:^ConfigProposalSetup = ConfigVotingSetup;
|
||||
_ get_vote_config(int critical?) inline_ref {
|
||||
var cs = config_param(11).begin_parse();
|
||||
_ get_vote_config_internal(int critical?, cell cparam11) inline_ref {
|
||||
var cs = cparam11.begin_parse();
|
||||
throw_unless(44, cs~load_uint(8) == 0x91);
|
||||
if (critical?) {
|
||||
cs~load_ref();
|
||||
|
@ -42,6 +42,10 @@ _ get_vote_config(int critical?) inline_ref {
|
|||
return parse_vote_config(cs.preload_ref());
|
||||
}
|
||||
|
||||
_ get_vote_config(int critical?) inline {
|
||||
return get_vote_config_internal(critical?, config_param(11));
|
||||
}
|
||||
|
||||
(int, int) check_validator_set(cell vset) {
|
||||
var cs = vset.begin_parse();
|
||||
throw_unless(9, cs~load_uint(8) == 0x12); ;; validators_ext#12 only
|
||||
|
@ -123,7 +127,7 @@ _ perform_action(cfg_dict, public_key, action, cs) inline_ref {
|
|||
}
|
||||
}
|
||||
|
||||
(cell, int, slice) get_current_vset() inline_ref {
|
||||
(cell, int, cell) get_current_vset() inline_ref {
|
||||
var vset = config_param(34);
|
||||
var cs = begin_parse(vset);
|
||||
;; validators_ext#12 utime_since:uint32 utime_until:uint32
|
||||
|
@ -131,13 +135,13 @@ _ perform_action(cfg_dict, public_key, action, cs) inline_ref {
|
|||
;; total_weight:uint64
|
||||
throw_unless(40, cs~load_uint(8) == 0x12);
|
||||
cs~skip_bits(32 + 32 + 16 + 16);
|
||||
int total_weight = cs~load_uint(64);
|
||||
return (vset, total_weight, cs);
|
||||
var (total_weight, dict) = (cs~load_uint(64), cs~load_dict());
|
||||
cs.end_parse();
|
||||
return (vset, total_weight, dict);
|
||||
}
|
||||
|
||||
(slice, int) get_validator_descr(int idx) inline_ref {
|
||||
var (vset, total_weight, cs) = get_current_vset();
|
||||
var dict = begin_cell().store_slice(cs).end_cell();
|
||||
var (vset, total_weight, dict) = get_current_vset();
|
||||
var (value, _) = dict.udict_get?(16, idx);
|
||||
return (value, total_weight);
|
||||
}
|
||||
|
@ -227,7 +231,7 @@ _ perform_action(cfg_dict, public_key, action, cs) inline_ref {
|
|||
}
|
||||
|
||||
slice update_proposal_status(slice rest, int weight_remaining, int critical?) inline_ref {
|
||||
var [min_tot_rounds, max_tot_rounds, min_wins, max_losses, _, _, _, _] = get_vote_config(critical?);
|
||||
var (min_tot_rounds, max_tot_rounds, min_wins, max_losses, _, _, _, _) = get_vote_config(critical?);
|
||||
var (rounds_remaining, wins, losses) = (rest~load_uint(8), rest~load_uint(8), rest~load_uint(8));
|
||||
losses -= (weight_remaining >= 0);
|
||||
if (losses > max_losses) {
|
||||
|
@ -241,8 +245,8 @@ slice update_proposal_status(slice rest, int weight_remaining, int critical?) in
|
|||
}
|
||||
return begin_cell()
|
||||
.store_uint(rounds_remaining, 8)
|
||||
.store_uint(losses, 8)
|
||||
.store_uint(wins, 8)
|
||||
.store_uint(losses, 8)
|
||||
.end_cell().begin_parse();
|
||||
}
|
||||
|
||||
|
@ -261,7 +265,7 @@ builder begin_pack_proposal_status(int expires, cell proposal, int critical?, ce
|
|||
var (pstatus, found?) = vote_dict.udict_get?(256, phash);
|
||||
ifnot (found?) {
|
||||
;; config proposal not found
|
||||
return (vote_dict, null(), false);
|
||||
return (vote_dict, null(), -1);
|
||||
}
|
||||
var (cur_vset, total_weight, _) = get_current_vset();
|
||||
int cur_vset_id = cur_vset.cell_hash();
|
||||
|
@ -269,7 +273,7 @@ builder begin_pack_proposal_status(int expires, cell proposal, int critical?, ce
|
|||
if (expires <= now()) {
|
||||
;; config proposal expired, delete and report not found
|
||||
vote_dict~udict_delete?(256, phash);
|
||||
return (vote_dict, null(), false);
|
||||
return (vote_dict, null(), -1);
|
||||
}
|
||||
if (vset_id != cur_vset_id) {
|
||||
;; config proposal belongs to a previous validator set
|
||||
|
@ -281,12 +285,12 @@ builder begin_pack_proposal_status(int expires, cell proposal, int critical?, ce
|
|||
if (rest.null?()) {
|
||||
;; discard proposal (existed for too many rounds, or too many losses)
|
||||
vote_dict~udict_delete?(256, phash);
|
||||
return (vote_dict, null(), false);
|
||||
return (vote_dict, null(), -1);
|
||||
}
|
||||
var (_, found?) = voters.udict_get?(16, idx);
|
||||
if (found?) {
|
||||
;; already voted for this proposal, ignore vote
|
||||
return (vote_dict, null(), false);
|
||||
return (vote_dict, null(), -2);
|
||||
}
|
||||
;; register vote
|
||||
voters~udict_set_builder(16, idx, begin_cell().store_uint(now(), 32));
|
||||
|
@ -296,16 +300,16 @@ builder begin_pack_proposal_status(int expires, cell proposal, int critical?, ce
|
|||
;; not enough votes, or proposal already accepted in this round
|
||||
;; simply update weight_remaining
|
||||
vote_dict~udict_set_builder(256, phash, begin_pack_proposal_status(expires, proposal, critical?, voters, weight_remaining, vset_id).store_slice(rest));
|
||||
return (vote_dict, null(), false);
|
||||
return (vote_dict, null(), 2);
|
||||
}
|
||||
;; proposal wins in this round
|
||||
var [min_tot_rounds, max_tot_rounds, min_wins, max_losses, _, _, _, _] = get_vote_config(critical?);
|
||||
var (min_tot_rounds, max_tot_rounds, min_wins, max_losses, _, _, _, _) = get_vote_config(critical?);
|
||||
var (rounds_remaining, wins, losses) = (rest~load_uint(8), rest~load_uint(8), rest~load_uint(8));
|
||||
wins += 1;
|
||||
if (wins >= min_wins) {
|
||||
;; proposal is accepted, remove and process
|
||||
vote_dict~udict_delete?(256, phash);
|
||||
return (vote_dict, proposal, critical?);
|
||||
return (vote_dict, proposal, 6 - critical?);
|
||||
}
|
||||
;; update proposal info
|
||||
vote_dict~udict_set_builder(256, phash,
|
||||
|
@ -313,7 +317,24 @@ builder begin_pack_proposal_status(int expires, cell proposal, int critical?, ce
|
|||
.store_uint(rounds_remaining, 8)
|
||||
.store_uint(wins, 8)
|
||||
.store_uint(losses, 8));
|
||||
return (vote_dict, null(), false);
|
||||
return (vote_dict, null(), 2);
|
||||
}
|
||||
|
||||
int proceed_register_vote(phash, idx, weight) impure inline_ref {
|
||||
var (cfg_dict, stored_seqno, public_key, vote_dict) = load_data();
|
||||
(vote_dict, var accepted_proposal, var status) = register_vote(vote_dict, phash, idx, weight);
|
||||
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
|
||||
ifnot (accepted_proposal.null?()) {
|
||||
var critical? = 6 - status;
|
||||
(cfg_dict, var param_id, var param_val) = accept_proposal(cfg_dict, accepted_proposal, critical?);
|
||||
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
|
||||
if (param_id) {
|
||||
commit();
|
||||
(cfg_dict, public_key) = perform_proposed_action(cfg_dict, public_key, param_id, param_val);
|
||||
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
(slice, int) scan_proposal(int phash, slice pstatus) inline_ref {
|
||||
|
@ -394,7 +415,7 @@ int register_voting_proposal(slice cs, int msg_value) impure inline_ref {
|
|||
}
|
||||
;; obtain vote proposal configuration
|
||||
var vote_cfg = get_vote_config(critical?);
|
||||
var [min_tot_rounds, max_tot_rounds, min_wins, max_losses, min_store_sec, max_store_sec, bit_price, cell_price] = vote_cfg;
|
||||
var (min_tot_rounds, max_tot_rounds, min_wins, max_losses, min_store_sec, max_store_sec, bit_price, cell_price) = vote_cfg;
|
||||
if (expire_at < min_store_sec) {
|
||||
return -0xc5787069; ;; expired
|
||||
}
|
||||
|
@ -486,6 +507,19 @@ int register_voting_proposal(slice cs, int msg_value) impure inline_ref {
|
|||
}
|
||||
return send_answer(s_addr, query_id, ans_tag, mode);
|
||||
}
|
||||
if (tag == 0x566f7465) {
|
||||
;; vote for a configuration proposal
|
||||
var signature = in_msg~load_bits(512);
|
||||
var msg_body = in_msg;
|
||||
var (sign_tag, idx, phash) = (in_msg~load_uint(32), in_msg~load_uint(16), in_msg~load_uint(256));
|
||||
in_msg.end_parse();
|
||||
throw_unless(37, sign_tag == 0x566f7445);
|
||||
var (vdescr, total_weight) = get_validator_descr(idx);
|
||||
var (val_pubkey, weight) = unpack_validator_descr(vdescr);
|
||||
throw_unless(34, check_data_signature(msg_body, signature, val_pubkey));
|
||||
int res = proceed_register_vote(phash, idx, weight);
|
||||
return send_confirmation(s_addr, query_id, res + 0xd6745240);
|
||||
}
|
||||
;; if tag is non-zero and its higher bit is zero, throw an exception (the message is an unsupported query)
|
||||
;; to bounce message back to sender
|
||||
throw_unless(37, (tag == 0) | (tag & (1 << 31)));
|
||||
|
@ -501,33 +535,24 @@ int register_voting_proposal(slice cs, int msg_value) impure inline_ref {
|
|||
throw_if(35, valid_until < now());
|
||||
throw_if(39, slice_depth(cs) > 128);
|
||||
var (cfg_dict, stored_seqno, public_key, vote_dict) = load_data();
|
||||
throw_unless(33, msg_seqno == stored_seqno);
|
||||
if (action == 0x566f7465) {
|
||||
;; vote for a configuration proposal
|
||||
var (idx, phash) = (cs~load_uint(16), cs~load_uint(256));
|
||||
cs.end_parse();
|
||||
var (vdescr, total_weight) = get_validator_descr(idx);
|
||||
var (val_pubkey, weight) = unpack_validator_descr(vdescr);
|
||||
throw_unless(34, check_data_signature(in_msg, signature, val_pubkey));
|
||||
accept_message();
|
||||
stored_seqno += 1;
|
||||
stored_seqno = (stored_seqno + 1) % (1 << 32);
|
||||
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
|
||||
commit();
|
||||
(vote_dict, var accepted_proposal, var critical?) = register_vote(vote_dict, phash, idx, weight);
|
||||
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
|
||||
ifnot (accepted_proposal.null?()) {
|
||||
(cfg_dict, var param_id, var param_val) = accept_proposal(cfg_dict, accepted_proposal, critical?);
|
||||
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
|
||||
if (param_id) {
|
||||
commit();
|
||||
(cfg_dict, public_key) = perform_proposed_action(cfg_dict, public_key, param_id, param_val);
|
||||
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
|
||||
}
|
||||
}
|
||||
proceed_register_vote(phash, idx, weight);
|
||||
return ();
|
||||
}
|
||||
throw_unless(33, msg_seqno == stored_seqno);
|
||||
throw_unless(34, check_signature(slice_hash(in_msg), signature, public_key));
|
||||
accept_message();
|
||||
stored_seqno += 1;
|
||||
stored_seqno = (stored_seqno + 1) % (1 << 32);
|
||||
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
|
||||
commit();
|
||||
(cfg_dict, public_key) = perform_action(cfg_dict, public_key, action, cs);
|
||||
|
@ -603,3 +628,14 @@ _ list_proposals() method_id {
|
|||
} until (~ f);
|
||||
return list;
|
||||
}
|
||||
|
||||
_ proposal_storage_price(int critical?, int seconds, int bits, int refs) method_id {
|
||||
var cfg_dict = get_data().begin_parse().preload_ref();
|
||||
var cparam11 = cfg_dict.idict_get_ref(32, 11);
|
||||
var (min_tot_rounds, max_tot_rounds, min_wins, max_losses, min_store_sec, max_store_sec, bit_price, cell_price) = get_vote_config_internal(critical?, cparam11);
|
||||
if (seconds < min_store_sec) {
|
||||
return -1;
|
||||
}
|
||||
seconds = min(seconds, max_store_sec);
|
||||
return (bit_price * (bits + 1024) + cell_price * (refs + 2)) * seconds;
|
||||
}
|
||||
|
|
|
@ -3,31 +3,44 @@
|
|||
"GetOpt.fif" include
|
||||
|
||||
"validator-to-sign.req" =: savefile
|
||||
false =: internal?
|
||||
-1 =: seqno
|
||||
-1 =: expire-at
|
||||
|
||||
{ ."usage: " @' $0 type ." <expire-at> <validator-idx> <proposal-hash> [<savefile>]" cr
|
||||
."Creates an unsigned request expiring at unixtime <expire-at> to vote for configuration proposal <proposal-hash> (decimal; prefix with '0x' if needed) on behalf of validator with zero-based index <validator-idx> in current validator set (as stored in configuration parameter 34)" cr
|
||||
{ ."usage: " @' $0 type ." (-i | <cfg-seqno> <expire-at>) <validator-idx> <proposal-hash> [<savefile>]" cr
|
||||
."Creates an unsigned request expiring at unixtime <expire-at> to vote for configuration proposal <proposal-hash> (decimal; prefix with '0x' if needed) on behalf of validator with zero-based index <validator-idx> in current validator set (as stored in configuration parameter 34)." cr
|
||||
."If -i is selected, prepares unsigned request to be incorporated into an internal message instead." cr
|
||||
."The result is saved into <savefile> (" savefile type ." by default) and output in hexadecimal form, to be signed later by the validator public key" cr 1 halt
|
||||
} : usage
|
||||
|
||||
$# dup 3 < swap 4 > or ' usage if
|
||||
4 :$1..n
|
||||
$# dup 3 < swap 5 > or ' usage if
|
||||
5 :$1..n
|
||||
{ $* @ dup null? ' dup ' uncons cond $* ! } : $next
|
||||
|
||||
$1 parse-int dup 30 1<< < { now + 1000 + 2000 /c 2000 * } if
|
||||
dup =: expire-at
|
||||
dup now <= abort"expiration time must be in the future"
|
||||
32 ufits not abort"invalid expiration time"
|
||||
$2 parse-int dup =: val-idx
|
||||
$1 "-i" $= { $next drop true =: internal? } if
|
||||
|
||||
internal? {
|
||||
$next parse-int =: seqno
|
||||
$next parse-int dup 30 1<< < { now + 1000 + 2000 /c 2000 * } if
|
||||
dup =: expire-at
|
||||
dup now <= abort"expiration time must be in the future"
|
||||
32 ufits not abort"invalid expiration time"
|
||||
} ifnot
|
||||
$# dup 2 < swap 3 > or ' usage if
|
||||
$1 parse-int dup =: val-idx
|
||||
16 ufits not abort"validator index out of range"
|
||||
$3 parse-int dup =: prop-hash
|
||||
$2 parse-int dup =: prop-hash
|
||||
256 ufits not abort"invalid proposal hash"
|
||||
$4 savefile replace-if-null =: savefile
|
||||
0 =: seqno
|
||||
$3 savefile replace-if-null =: savefile
|
||||
|
||||
."Creating a request expiring at " expire-at .
|
||||
."Creating a request " internal? { ."with seqno " seqno . ."expiring at " expire-at . } ifnot
|
||||
."to vote for configuration proposal 0x" prop-hash 64x.
|
||||
."on behalf of validator with index " val-idx . cr
|
||||
|
||||
B{566f7465} seqno 32 u>B B+ expire-at 32 u>B B+ val-idx 16 u>B B+ prop-hash 256 u>B B+
|
||||
internal? { B{566f7445} } {
|
||||
B{566f7465} seqno 32 u>B B+ expire-at 32 u>B B+
|
||||
} cond
|
||||
val-idx 16 u>B B+ prop-hash 256 u>B B+
|
||||
dup Bx. cr
|
||||
dup B>base64url type cr
|
||||
savefile tuck B>file ."Saved to file " type cr
|
||||
|
|
|
@ -3,49 +3,70 @@
|
|||
"GetOpt.fif" include
|
||||
|
||||
"vote-query.boc" =: savefile
|
||||
false =: internal?
|
||||
-1 =: seqno
|
||||
0 0 2=: config-addr
|
||||
-1 =: expire-at
|
||||
|
||||
{ ."usage: " @' $0 type ." <config-addr> <expire-at> <validator-idx> <proposal-hash> <validator-pubkey> <validator-signature> [<savefile>]" cr
|
||||
."Creates an external message addressed to the configuration smart contract <config-addr> containing a signed request expiring at unixtime <expire-at> to vote for configuration proposal <proposal-hash> (decimal; prefix with '0x' if needed) on behalf of validator with zero-based index <validator-idx> and (Base64) public key <validator-pubkey> in current validator set (as stored in configuration parameter 34)" cr
|
||||
{ ."usage: " @' $0 type ." (-i | <config-addr> <config-seqno> <expire-at>) <validator-idx> <proposal-hash> <validator-pubkey> <validator-signature> [<savefile>]" cr
|
||||
."Creates an external message addressed to the configuration smart contract <config-addr> and current sequence number <config-seqno> containing a signed request expiring at unixtime <expire-at> to vote for configuration proposal <proposal-hash> (decimal; prefix with '0x' if needed) on behalf of validator with zero-based index <validator-idx> and (Base64) public key <validator-pubkey> in current validator set (as stored in configuration parameter 34)" cr
|
||||
."<validator-signature> must be the base64 representation of Ed25519 signature of the previously generated unsigned request by means of <validator-pubkey>" cr
|
||||
."If -i is selected, instead generates the body of an internal message to be sent to the configuration smart contract from any smartcontract residing in the masterchain" cr
|
||||
."The result is saved into <savefile> (" savefile type ." by default), to be sent later by the lite-client" cr 1 halt
|
||||
} : usage
|
||||
|
||||
$# dup 6 < swap 7 > or ' usage if
|
||||
7 :$1..n
|
||||
$# dup 5 < swap 8 > or ' usage if
|
||||
8 :$1..n
|
||||
|
||||
$1 true parse-load-address drop over 1+ abort"configuration smart contract must be in masterchain"
|
||||
2=: config-addr
|
||||
$2 parse-int dup 30 1<< < { now + 1000 + 2000 /c 2000 * } if
|
||||
dup =: expire-at
|
||||
dup now <= abort"expiration time must be in the future"
|
||||
32 ufits not abort"invalid expiration time"
|
||||
$3 parse-int dup =: val-idx
|
||||
{ $* @ dup null? ' dup ' uncons cond $* ! } : $next
|
||||
$1 "-i" $= { $next drop true =: internal? "vote-msg-body.boc" =: savefile } if
|
||||
|
||||
internal? {
|
||||
$next true parse-load-address drop over 1+ abort"configuration smart contract must be in masterchain"
|
||||
2=: config-addr
|
||||
$next parse-int =: seqno
|
||||
$next parse-int dup 30 1<< < { now + 1000 + 2000 /c 2000 * } if
|
||||
dup =: expire-at
|
||||
dup now <= abort"expiration time must be in the future"
|
||||
32 ufits not abort"invalid expiration time"
|
||||
} ifnot
|
||||
$# dup 4 < swap 5 > or ' usage if
|
||||
$1 parse-int dup =: val-idx
|
||||
16 ufits not abort"validator index out of range"
|
||||
$4 parse-int dup =: prop-hash
|
||||
$2 parse-int dup =: prop-hash
|
||||
256 ufits not abort"invalid proposal hash"
|
||||
$5 base64>B dup Blen 36 <> abort"validator Ed25519 public key must be exactly 36 bytes long"
|
||||
$3 base64>B dup Blen 36 <> abort"validator Ed25519 public key must be exactly 36 bytes long"
|
||||
32 B>u@+ 0xC6B41348 <> abort"invalid Ed25519 public key: unknown magic number"
|
||||
=: pubkey
|
||||
$6 base64>B dup Blen 64 <> abort"validator Ed25519 signature must be exactly 64 bytes long"
|
||||
$4 base64>B dup Blen 64 <> abort"validator Ed25519 signature must be exactly 64 bytes long"
|
||||
=: signature
|
||||
$7 savefile replace-if-null =: savefile
|
||||
0 =: seqno
|
||||
$5 savefile replace-if-null =: savefile
|
||||
|
||||
."Creating an external message to configuration smart contract "
|
||||
config-addr 2dup 6 .Addr ." = " .addr cr
|
||||
."containing a signed request expiring at " expire-at .
|
||||
internal? {
|
||||
."Creating the body of an internal message to be sent to the configuration smart contract" cr }
|
||||
{ ."Creating an external message to configuration smart contract "
|
||||
config-addr 2dup 6 .Addr ." = " .addr cr
|
||||
} cond
|
||||
."containing a signed request " internal? { ."expiring at " expire-at . } ifnot
|
||||
."to vote for configuration proposal 0x" prop-hash 64x.
|
||||
."on behalf of validator with index " val-idx . "and public key" pubkey 64x. cr
|
||||
."on behalf of validator with index " val-idx . "and public key" pubkey Bx. cr
|
||||
|
||||
B{566f7465} seqno 32 u>B B+ expire-at 32 u>B B+ val-idx 16 u>B B+ prop-hash 256 u>B B+
|
||||
dup =: to_sign
|
||||
internal? { B{566f7445} } {
|
||||
B{566f7465} seqno 32 u>B B+ expire-at 32 u>B B+
|
||||
} cond
|
||||
val-idx 16 u>B B+ prop-hash 256 u>B B+ dup =: to_sign
|
||||
."String to sign is " Bx. cr
|
||||
|
||||
to_sign signature pubkey ed25519_chksign not abort"Ed25519 signature is invalid"
|
||||
."Provided a valid Ed25519 signature " signature Bx. ." with validator public key " pubkey Bx. cr
|
||||
|
||||
<b b{1000100} s, config-addr addr, 0 Gram, b{00} s,
|
||||
now 32 << prop-hash 32 1<< mod + =: query-id
|
||||
|
||||
<b internal? { x{566f7465} s, query-id 64 u, }
|
||||
{ b{1000100} s, config-addr addr, 0 Gram, b{00} s, } cond
|
||||
signature B, to_sign B, b>
|
||||
cr ."External message is " dup <s csr. cr
|
||||
cr
|
||||
internal? { ."Internal message body is " } { ."External message is " } cond
|
||||
dup <s csr. cr
|
||||
|
||||
2 boc+>B savefile tuck B>file ."Saved to file " type cr
|
||||
|
|
|
@ -41,7 +41,11 @@ boc-filename dup "null" $= {
|
|||
} cond
|
||||
=: param-value
|
||||
|
||||
{ 2drop true } : is-valid-config?
|
||||
{ dup -1000 = { drop <s ref@ <s 12 u@ 0xFF0 = } {
|
||||
dup -1001 = { drop <s ref@ <s 12 u@ 0xFF0 = } {
|
||||
2drop true
|
||||
} cond } cond
|
||||
} : is-valid-config?
|
||||
|
||||
dup param-idx is-valid-config? not abort"not a valid value for chosen configuration parameter"
|
||||
|
||||
|
@ -59,5 +63,11 @@ now 32 << param-idx + =: query-id
|
|||
|
||||
dup ."resulting internal message body: " <s csr. cr
|
||||
2 boc+>B dup Bx. cr
|
||||
|
||||
param-value dup null? { drop } {
|
||||
totalcsize swap ."(a total of " . ."data bits, " . ."cell references -> "
|
||||
drop dup Blen . ."BoC data bytes)" cr
|
||||
} cond
|
||||
|
||||
savefile tuck B>file
|
||||
."(Saved to file " type .")" cr
|
||||
|
|
65
crypto/smartcont/create-config-upgrade-proposal.fif
Normal file
65
crypto/smartcont/create-config-upgrade-proposal.fif
Normal file
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/fift -s
|
||||
"Asm.fif" include
|
||||
"TonUtil.fif" include
|
||||
"GetOpt.fif" include
|
||||
|
||||
// only the next three lines differ in elector/configuration smart contract upgrades
|
||||
"configuration" =: name
|
||||
"auto/config-code.fif" =: src-file
|
||||
-1000 =: param-idx
|
||||
|
||||
86400 30 * =: expire-in
|
||||
true =: critical
|
||||
-1 =: old-hash
|
||||
|
||||
{ show-options-help 1 halt } : usage
|
||||
{ name $+ } : +name
|
||||
|
||||
begin-options
|
||||
" [-s <fift-asm-code>] [-x <expire-in>] [-H <old-hash>] [<savefile>]" +cr +tab
|
||||
+"Creates a new configuration proposal for upgrading the " +name +" smart contract code to <fift-asm-code> ('" src-file $+ +"' by default), "
|
||||
+"and saves it as an internal message body into <savefile>.boc ('config-msg-body.boc' by default)"
|
||||
disable-digit-options generic-help-setopt
|
||||
"x" "--expires-in" { parse-int =: expire-in } short-long-option-arg
|
||||
"Sets proposal expiration time in seconds (default " expire-in (.) $+ +")" option-help
|
||||
"s" "--source" { =: src-file } short-long-option-arg
|
||||
"Fift assembler source file for the new " +name +" smart contract code ('"
|
||||
src-file $+ +"' by default)" option-help
|
||||
"H" "--old-hash" { (hex-number) not abort"256-bit hex number expected as hash" =: old-hash }
|
||||
short-long-option-arg
|
||||
"Sets the required cell hash of existing parameter value (0 means no value)" option-help
|
||||
"h" "--help" { usage } short-long-option
|
||||
"Shows a help message" option-help
|
||||
parse-options
|
||||
|
||||
$# 1 > ' usage if
|
||||
1 :$1..n
|
||||
|
||||
$1 "config-msg-body.boc" replace-if-null =: savefile
|
||||
expire-in now + =: expire-at
|
||||
|
||||
."Assembling new " name type ." smart contract code from " src-file type cr
|
||||
src-file include
|
||||
dup <s 12 u@ 0xFF0 <> abort"not valid smart contract code"
|
||||
<b swap ref, b> =: param-value
|
||||
|
||||
critical { ."Critical" } { ."Non-critical" } cond
|
||||
." configuration proposal for configuration parameter " param-idx .
|
||||
."will expire at " expire-at . ."(in " expire-in . ."seconds)" cr
|
||||
|
||||
now 32 << param-idx + =: query-id
|
||||
."Query id is " query-id . cr
|
||||
|
||||
// create message body
|
||||
<b x{6e565052} s, query-id 64 u, expire-at 32 u,
|
||||
<b x{f3} s, param-idx 32 i, param-value dict,
|
||||
old-hash tuck 0>= tuck 1 i, -rot { 256 u, } { drop } cond b> ref,
|
||||
critical 1 i, b>
|
||||
|
||||
dup ."resulting internal message body: " <s csr. cr
|
||||
2 boc+>B dup Bx. cr
|
||||
param-value totalcsize swap ."(a total of " . ."data bits, " . ."cell references -> "
|
||||
drop dup Blen . ."BoC data bytes)" cr
|
||||
|
||||
savefile tuck B>file
|
||||
."(Saved to file " type .")" cr
|
65
crypto/smartcont/create-elector-upgrade-proposal.fif
Normal file
65
crypto/smartcont/create-elector-upgrade-proposal.fif
Normal file
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/fift -s
|
||||
"Asm.fif" include
|
||||
"TonUtil.fif" include
|
||||
"GetOpt.fif" include
|
||||
|
||||
// only the next three lines differ in elector/configuration smart contract upgrades
|
||||
"elector" =: name
|
||||
"auto/elector-code.fif" =: src-file
|
||||
-1001 =: param-idx
|
||||
|
||||
86400 30 * =: expire-in
|
||||
true =: critical
|
||||
-1 =: old-hash
|
||||
|
||||
{ show-options-help 1 halt } : usage
|
||||
{ name $+ } : +name
|
||||
|
||||
begin-options
|
||||
" [-s <fift-asm-code>] [-x <expire-in>] [-H <old-hash>] [<savefile>]" +cr +tab
|
||||
+"Creates a new configuration proposal for upgrading the " +name +" smart contract code to <fift-asm-code> ('" src-file $+ +"' by default), "
|
||||
+"and saves it as an internal message body into <savefile>.boc ('config-msg-body.boc' by default)"
|
||||
disable-digit-options generic-help-setopt
|
||||
"x" "--expires-in" { parse-int =: expire-in } short-long-option-arg
|
||||
"Sets proposal expiration time in seconds (default " expire-in (.) $+ +")" option-help
|
||||
"s" "--source" { =: src-file } short-long-option-arg
|
||||
"Fift assembler source file for the new " +name +" smart contract code ('"
|
||||
src-file $+ +"' by default)" option-help
|
||||
"H" "--old-hash" { (hex-number) not abort"256-bit hex number expected as hash" =: old-hash }
|
||||
short-long-option-arg
|
||||
"Sets the required cell hash of existing parameter value (0 means no value)" option-help
|
||||
"h" "--help" { usage } short-long-option
|
||||
"Shows a help message" option-help
|
||||
parse-options
|
||||
|
||||
$# 1 > ' usage if
|
||||
1 :$1..n
|
||||
|
||||
$1 "config-msg-body.boc" replace-if-null =: savefile
|
||||
expire-in now + =: expire-at
|
||||
|
||||
."Assembling new " name type ." smart contract code from " src-file type cr
|
||||
src-file include
|
||||
dup <s 12 u@ 0xFF0 <> abort"not valid smart contract code"
|
||||
<b swap ref, b> =: param-value
|
||||
|
||||
critical { ."Critical" } { ."Non-critical" } cond
|
||||
." configuration proposal for configuration parameter " param-idx .
|
||||
."will expire at " expire-at . ."(in " expire-in . ."seconds)" cr
|
||||
|
||||
now 32 << param-idx + =: query-id
|
||||
."Query id is " query-id . cr
|
||||
|
||||
// create message body
|
||||
<b x{6e565052} s, query-id 64 u, expire-at 32 u,
|
||||
<b x{f3} s, param-idx 32 i, param-value dict,
|
||||
old-hash tuck 0>= tuck 1 i, -rot { 256 u, } { drop } cond b> ref,
|
||||
critical 1 i, b>
|
||||
|
||||
dup ."resulting internal message body: " <s csr. cr
|
||||
2 boc+>B dup Bx. cr
|
||||
param-value totalcsize swap ."(a total of " . ."data bits, " . ."cell references -> "
|
||||
drop dup Blen . ."BoC data bytes)" cr
|
||||
|
||||
savefile tuck B>file
|
||||
."(Saved to file " type .")" cr
|
Loading…
Add table
Add a link
Reference in a new issue