mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
emergency update
This commit is contained in:
parent
5d846e0aaf
commit
9f351fc29f
87 changed files with 2486 additions and 655 deletions
|
@ -23,6 +23,25 @@
|
|||
.end_cell());
|
||||
}
|
||||
|
||||
;; [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)];
|
||||
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();
|
||||
throw_unless(44, cs~load_uint(8) == 0x91);
|
||||
if (critical?) {
|
||||
cs~load_ref();
|
||||
}
|
||||
return parse_vote_config(cs.preload_ref());
|
||||
}
|
||||
|
||||
(int, int) check_validator_set(cell vset) {
|
||||
var cs = vset.begin_parse();
|
||||
throw_unless(9, cs~load_uint(8) == 0x12); ;; validators_ext#12 only
|
||||
|
@ -46,53 +65,14 @@
|
|||
.end_cell(), mode);
|
||||
}
|
||||
|
||||
() send_confirmation(addr, query_id, ans_tag) impure {
|
||||
() send_confirmation(addr, query_id, ans_tag) impure inline {
|
||||
return send_answer(addr, query_id, ans_tag, 64);
|
||||
}
|
||||
|
||||
() send_error(addr, query_id, ans_tag) impure {
|
||||
() send_error(addr, query_id, ans_tag) impure inline {
|
||||
return send_answer(addr, query_id, ans_tag, 64);
|
||||
}
|
||||
|
||||
() recv_internal(cell in_msg_cell, slice in_msg) impure {
|
||||
var cs = in_msg_cell.begin_parse();
|
||||
var flags = cs~load_uint(4); ;; int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
|
||||
var s_addr = cs~load_msg_addr();
|
||||
(int src_wc, int src_addr) = s_addr.parse_std_addr();
|
||||
if ((src_wc + 1) | (flags & 1) | in_msg.slice_empty?()) {
|
||||
;; source not in masterchain, or a bounced message, or a simple transfer
|
||||
return ();
|
||||
}
|
||||
int tag = in_msg~load_uint(32);
|
||||
int query_id = in_msg~load_uint(64);
|
||||
if (tag == 0x4e565354) {
|
||||
;; set next validator set
|
||||
var vset = in_msg~load_ref();
|
||||
in_msg.end_parse();
|
||||
var elector_param = config_param(1);
|
||||
var elector_addr = cell_null?(elector_param) ? -1 : elector_param.begin_parse().preload_uint(256);
|
||||
var ok = false;
|
||||
if (src_addr == elector_addr) {
|
||||
;; message from elector smart contract
|
||||
;; set next validator set
|
||||
(var t_since, var t_until) = check_validator_set(vset);
|
||||
var t = now();
|
||||
ok = (t_since > t) & (t_until > t_since);
|
||||
}
|
||||
if (ok) {
|
||||
set_conf_param(36, vset);
|
||||
;; send confirmation
|
||||
return send_confirmation(s_addr, query_id, 0xee764f4b);
|
||||
} else {
|
||||
return send_error(s_addr, query_id, 0xee764f6f);
|
||||
}
|
||||
}
|
||||
;; 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)));
|
||||
;; do nothing for other internal messages
|
||||
}
|
||||
|
||||
;; forward a message to elector smart contract to make it upgrade its code
|
||||
() change_elector_code(slice cs) impure {
|
||||
var dest_addr = config_param(1).begin_parse().preload_uint(256);
|
||||
|
@ -114,7 +94,7 @@
|
|||
_ perform_action(cfg_dict, public_key, action, cs) {
|
||||
if (action == 0x43665021) {
|
||||
;; change one configuration parameter
|
||||
var param_index = cs~load_uint(32);
|
||||
var param_index = cs~load_int(32);
|
||||
var param_value = cs~load_ref();
|
||||
cs.end_parse();
|
||||
cfg_dict~idict_set_ref(32, param_index, param_value);
|
||||
|
@ -143,11 +123,8 @@ _ perform_action(cfg_dict, public_key, action, cs) {
|
|||
}
|
||||
}
|
||||
|
||||
(slice, int) get_validator_descr(int idx) inline_ref {
|
||||
(cell, int, slice) get_current_vset() inline_ref {
|
||||
var vset = config_param(34);
|
||||
if (vset.null?()) {
|
||||
return (null(), 0);
|
||||
}
|
||||
var cs = begin_parse(vset);
|
||||
;; validators_ext#12 utime_since:uint32 utime_until:uint32
|
||||
;; total:(## 16) main:(## 16) { main <= total } { main >= 1 }
|
||||
|
@ -155,6 +132,11 @@ _ perform_action(cfg_dict, public_key, action, cs) {
|
|||
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);
|
||||
}
|
||||
|
||||
(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 (value, _) = dict.udict_get?(16, idx);
|
||||
return (value, total_weight);
|
||||
|
@ -169,6 +151,40 @@ _ perform_action(cfg_dict, public_key, action, cs) {
|
|||
return (cs~load_uint(256), cs~load_uint(64));
|
||||
}
|
||||
|
||||
;; cfg_proposal#f3 param_id:int32 param_value:(Maybe ^Cell) if_hash_equal:(Maybe uint256)
|
||||
;; c -> (param-id param-cell maybe-hash)
|
||||
(int, cell, int) parse_config_proposal(cell c) inline_ref {
|
||||
var cs = c.begin_parse();
|
||||
throw_unless(44, cs~load_int(8) == 0xf3 - 0x100);
|
||||
var (id, val, hash) = (cs~load_int(32), cs~load_maybe_ref(), cs~load_int(1));
|
||||
if (hash) {
|
||||
hash = cs~load_uint(256);
|
||||
} else {
|
||||
hash = -1;
|
||||
}
|
||||
cs.end_parse();
|
||||
return (id, val, hash);
|
||||
}
|
||||
|
||||
;; cfg_proposal_status#ce expires:uint32 proposal:^ConfigProposal is_critical:Bool
|
||||
;; voters:(HashmapE 16 True) remaining_weight:int64 validator_set_id:uint256
|
||||
;; rounds_remaining:uint8 wins:uint8 losses:uint8 = ConfigProposalStatus;
|
||||
(int, cell, int, cell, int, int, slice) unpack_proposal_status(slice cs) inline_ref {
|
||||
throw_unless(44, cs~load_int(8) == 0xce - 0x100);
|
||||
return (cs~load_uint(32), cs~load_ref(), cs~load_int(1), cs~load_dict(), cs~load_int(64), cs~load_uint(256), cs);
|
||||
}
|
||||
|
||||
builder begin_pack_proposal_status(int expires, cell proposal, int critical?, cell voters, int weight_remaining, int vset_id) inline {
|
||||
return begin_cell()
|
||||
.store_int(0xce - 0x100, 8)
|
||||
.store_uint(expires, 32)
|
||||
.store_ref(proposal)
|
||||
.store_int(critical?, 1)
|
||||
.store_dict(voters)
|
||||
.store_int(weight_remaining, 64)
|
||||
.store_uint(vset_id, 256);
|
||||
}
|
||||
|
||||
(cell, int, int, slice) new_proposal(cs) inline {
|
||||
return (null(), 0, 0, cs);
|
||||
}
|
||||
|
@ -216,6 +232,141 @@ builder pack_proposal(cell voters, int sum_weight, int vset_id, slice body) inli
|
|||
}
|
||||
}
|
||||
|
||||
int register_voting_proposal(slice cs, int msg_value) inline_ref {
|
||||
var (expire_at, proposal, critical?) = (cs~load_uint(32), cs~load_ref(), cs~load_int(1));
|
||||
if (expire_at >> 30) {
|
||||
expire_at -= now();
|
||||
}
|
||||
var (param_id, param_val, hash) = parse_config_proposal(proposal);
|
||||
if (hash >= 0) {
|
||||
cell cur_val = config_param(param_id);
|
||||
int cur_hash = null?(cur_val) ? 0 : cell_hash(cur_val);
|
||||
if (cur_hash != hash) {
|
||||
hash = -0xe2646356; ;; bad current value
|
||||
}
|
||||
} else {
|
||||
var m_params = config_param(9);
|
||||
var (_, found?) = m_params.idict_get?(32, param_id);
|
||||
if (found?) {
|
||||
hash = -0xcd506e6c; ;; cannot set mandatory parameter to null
|
||||
}
|
||||
}
|
||||
if (param_val.cell_depth() >= 256) {
|
||||
hash = -0xc2616456; ;; bad value
|
||||
}
|
||||
if (hash < -1) {
|
||||
return hash; ;; return error if any
|
||||
}
|
||||
ifnot (critical?) {
|
||||
var crit_params = config_param(10);
|
||||
var (_, found?) = crit_params.idict_get?(32, param_id);
|
||||
if (found?) {
|
||||
hash = -0xc3726954; ;; trying to set a critical parameter without critical flag
|
||||
}
|
||||
}
|
||||
if (hash < -1) {
|
||||
return hash;
|
||||
}
|
||||
;; 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;
|
||||
if (expire_at < min_store_sec) {
|
||||
return -0xc5787069; ;; expired
|
||||
}
|
||||
expire_at = min(expire_at, max_store_sec);
|
||||
;; compute price
|
||||
var (_, bits, refs) = compute_data_size(param_val, 1024);
|
||||
var pps = bit_price * (bits + 1024) + cell_price * (refs + 2);
|
||||
var price = pps * expire_at;
|
||||
expire_at += now();
|
||||
var (cfg_dict, stored_seqno, public_key, vote_dict) = load_data();
|
||||
int phash = proposal.cell_hash();
|
||||
var (pstatus, found?) = vote_dict.udict_get?(256, phash);
|
||||
if (found?) {
|
||||
;; proposal already exists; we can only extend it
|
||||
var (expires, r_proposal, r_critical?, voters, weight_remaining, vset_id, rest) = unpack_proposal_status(pstatus);
|
||||
if (r_critical? != critical?) {
|
||||
return -0xc3726955; ;; cannot upgrade critical parameter to non-critical...
|
||||
}
|
||||
if (expires >= expire_at) {
|
||||
return -0xc16c7245; ;; proposal already exists
|
||||
}
|
||||
;; recompute price
|
||||
price = pps * (expire_at - expires + 16384);
|
||||
if (msg_value - price < (1 << 30)) {
|
||||
return -0xf0617924; ;; need more money
|
||||
}
|
||||
;; update expiration time
|
||||
vote_dict~udict_set_builder(256, phash, begin_pack_proposal_status(expire_at, r_proposal, r_critical?, voters, weight_remaining, vset_id).store_slice(rest));
|
||||
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
|
||||
return price;
|
||||
}
|
||||
if (msg_value - price < (1 << 30)) {
|
||||
return -0xf0617924; ;; need more money
|
||||
}
|
||||
;; obtain current validator set data
|
||||
var (vset, total_weight, _) = get_current_vset();
|
||||
int weight_remaining = muldiv(total_weight, 2, 3) + 1;
|
||||
;; create new proposal
|
||||
vote_dict~udict_set_builder(256, phash,
|
||||
begin_pack_proposal_status(expire_at, proposal, critical?, null(), weight_remaining, vset.cell_hash())
|
||||
.store_uint(max_tot_rounds, 8).store_uint(0, 16));
|
||||
store_data(cfg_dict, stored_seqno, public_key, vote_dict);
|
||||
return price;
|
||||
}
|
||||
|
||||
() recv_internal(int msg_value, cell in_msg_cell, slice in_msg) impure {
|
||||
var cs = in_msg_cell.begin_parse();
|
||||
var flags = cs~load_uint(4); ;; int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
|
||||
var s_addr = cs~load_msg_addr();
|
||||
(int src_wc, int src_addr) = s_addr.parse_std_addr();
|
||||
if ((src_wc + 1) | (flags & 1) | in_msg.slice_empty?()) {
|
||||
;; source not in masterchain, or a bounced message, or a simple transfer
|
||||
return ();
|
||||
}
|
||||
int tag = in_msg~load_uint(32);
|
||||
int query_id = in_msg~load_uint(64);
|
||||
if (tag == 0x4e565354) {
|
||||
;; set next validator set
|
||||
var vset = in_msg~load_ref();
|
||||
in_msg.end_parse();
|
||||
var elector_param = config_param(1);
|
||||
var elector_addr = cell_null?(elector_param) ? -1 : elector_param.begin_parse().preload_uint(256);
|
||||
var ok = false;
|
||||
if (src_addr == elector_addr) {
|
||||
;; message from elector smart contract
|
||||
;; set next validator set
|
||||
(var t_since, var t_until) = check_validator_set(vset);
|
||||
var t = now();
|
||||
ok = (t_since > t) & (t_until > t_since);
|
||||
}
|
||||
if (ok) {
|
||||
set_conf_param(36, vset);
|
||||
;; send confirmation
|
||||
return send_confirmation(s_addr, query_id, 0xee764f4b);
|
||||
} else {
|
||||
return send_error(s_addr, query_id, 0xee764f6f);
|
||||
}
|
||||
}
|
||||
if (tag == 0x6e565052) {
|
||||
;; new voting proposal
|
||||
var price = register_voting_proposal(cs, msg_value);
|
||||
int mode = 64;
|
||||
int ans_tag = - price;
|
||||
if (price >= 0) {
|
||||
;; ok, debit price
|
||||
raw_reserve(price, 4);
|
||||
ans_tag = 0xee565052;
|
||||
mode = 128;
|
||||
}
|
||||
return send_answer(s_addr, query_id, ans_tag, mode);
|
||||
}
|
||||
;; 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)));
|
||||
;; do nothing for other internal messages
|
||||
}
|
||||
|
||||
() recv_external(slice in_msg) impure {
|
||||
var signature = in_msg~load_bits(512);
|
||||
var cs = in_msg;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue