1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-02-13 03:32:22 +00:00

Merge pull request #716 from ton-blockchain/rc

Merge developer branch
This commit is contained in:
EmelyanenkoK 2023-05-31 16:22:56 +03:00 committed by GitHub
commit c46bf00fd1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 253 additions and 85 deletions

View file

@ -36,6 +36,7 @@ jobs:
- name: Simple binaries test - name: Simple binaries test
run: | run: |
sudo mv /nix/store /nix/store2
artifacts/validator-engine -V artifacts/validator-engine -V
artifacts/lite-client -V artifacts/lite-client -V
artifacts/fift -V artifacts/fift -V

View file

@ -33,6 +33,7 @@ jobs:
- name: Simple binaries test - name: Simple binaries test
run: | run: |
sudo mv /nix/store /nix/store2
artifacts/validator-engine -V artifacts/validator-engine -V
artifacts/lite-client -V artifacts/lite-client -V
artifacts/fift -V artifacts/fift -V

View file

@ -35,6 +35,7 @@ jobs:
- name: Simple binaries test - name: Simple binaries test
run: | run: |
sudo mv /nix/store /nix/store2
artifacts/validator-engine -V artifacts/validator-engine -V
artifacts/lite-client -V artifacts/lite-client -V
artifacts/fift -V artifacts/fift -V

View file

@ -31,6 +31,7 @@ jobs:
- name: Simple binaries test - name: Simple binaries test
run: | run: |
sudo mv /nix/store /nix/store2
artifacts/validator-engine -V artifacts/validator-engine -V
artifacts/lite-client -V artifacts/lite-client -V
artifacts/fift -V artifacts/fift -V

View file

@ -1,3 +1,9 @@
## 2023.06 Update
1. (disabled by default) New deflation mechanisms: partial fee burning and blackhole address
2. Storage-contract improvement
Besides the work of the core team, this update is based on the efforts of @DearJohnDoe from Tonbyte (Storage-contract improvement).
## 2023.05 Update ## 2023.05 Update
1. Archive manager optimization 1. Archive manager optimization
2. A series of catchain (basic consensus protocol) security improvements 2. A series of catchain (basic consensus protocol) security improvements

View file

@ -1364,42 +1364,61 @@ std::ostream& operator<<(std::ostream& os, const CurrencyCollection& cc) {
bool ValueFlow::set_zero() { bool ValueFlow::set_zero() {
return from_prev_blk.set_zero() && to_next_blk.set_zero() && imported.set_zero() && exported.set_zero() && return from_prev_blk.set_zero() && to_next_blk.set_zero() && imported.set_zero() && exported.set_zero() &&
fees_collected.set_zero() && fees_imported.set_zero() && recovered.set_zero() && created.set_zero() && fees_collected.set_zero() && fees_imported.set_zero() && recovered.set_zero() && created.set_zero() &&
minted.set_zero(); minted.set_zero() && burned.set_zero();
} }
bool ValueFlow::validate() const { bool ValueFlow::validate() const {
return is_valid() && from_prev_blk + imported + fees_imported + created + minted + recovered == return is_valid() && from_prev_blk + imported + fees_imported + created + minted + recovered ==
to_next_blk + exported + fees_collected; to_next_blk + exported + fees_collected + burned;
} }
bool ValueFlow::store(vm::CellBuilder& cb) const { bool ValueFlow::store(vm::CellBuilder& cb) const {
vm::CellBuilder cb2; vm::CellBuilder cb2;
return cb.store_long_bool(block::gen::ValueFlow::cons_tag[0], 32) // value_flow ^[ auto type = burned.is_zero() ? block::gen::ValueFlow::value_flow : block::gen::ValueFlow::value_flow_v2;
&& from_prev_blk.store(cb2) // from_prev_blk:CurrencyCollection return cb.store_long_bool(block::gen::ValueFlow::cons_tag[type], 32) // ^[
&& to_next_blk.store(cb2) // to_next_blk:CurrencyCollection && from_prev_blk.store(cb2) // from_prev_blk:CurrencyCollection
&& imported.store(cb2) // imported:CurrencyCollection && to_next_blk.store(cb2) // to_next_blk:CurrencyCollection
&& exported.store(cb2) // exported:CurrencyCollection && imported.store(cb2) // imported:CurrencyCollection
&& cb.store_ref_bool(cb2.finalize()) // ] && exported.store(cb2) // exported:CurrencyCollection
&& fees_collected.store(cb) // fees_collected:CurrencyCollection && cb.store_ref_bool(cb2.finalize()) // ]
&& fees_imported.store(cb2) // ^[ fees_imported:CurrencyCollection && fees_collected.store(cb) // fees_collected:CurrencyCollection
&& recovered.store(cb2) // recovered:CurrencyCollection && (burned.is_zero() || burned.store(cb)) // fees_burned:CurrencyCollection
&& created.store(cb2) // created:CurrencyCollection && fees_imported.store(cb2) // ^[ fees_imported:CurrencyCollection
&& minted.store(cb2) // minted:CurrencyCollection && recovered.store(cb2) // recovered:CurrencyCollection
&& cb.store_ref_bool(cb2.finalize()); // ] = ValueFlow; && created.store(cb2) // created:CurrencyCollection
&& minted.store(cb2) // minted:CurrencyCollection
&& cb.store_ref_bool(cb2.finalize()); // ] = ValueFlow;
} }
bool ValueFlow::fetch(vm::CellSlice& cs) { bool ValueFlow::fetch(vm::CellSlice& cs) {
block::gen::ValueFlow::Record f; if (cs.size() < 32) {
if (!(tlb::unpack(cs, f) && from_prev_blk.validate_unpack(std::move(f.r1.from_prev_blk)) &&
to_next_blk.validate_unpack(std::move(f.r1.to_next_blk)) &&
imported.validate_unpack(std::move(f.r1.imported)) && exported.validate_unpack(std::move(f.r1.exported)) &&
fees_collected.validate_unpack(std::move(f.fees_collected)) &&
fees_imported.validate_unpack(std::move(f.r2.fees_imported)) &&
recovered.validate_unpack(std::move(f.r2.recovered)) && created.validate_unpack(std::move(f.r2.created)) &&
minted.validate_unpack(std::move(f.r2.minted)))) {
return invalidate(); return invalidate();
} }
return true; auto tag = cs.prefetch_ulong(32);
block::gen::ValueFlow::Record_value_flow f1;
if (tag == block::gen::ValueFlow::cons_tag[block::gen::ValueFlow::value_flow] && tlb::unpack(cs, f1) &&
from_prev_blk.validate_unpack(std::move(f1.r1.from_prev_blk)) &&
to_next_blk.validate_unpack(std::move(f1.r1.to_next_blk)) &&
imported.validate_unpack(std::move(f1.r1.imported)) && exported.validate_unpack(std::move(f1.r1.exported)) &&
fees_collected.validate_unpack(std::move(f1.fees_collected)) && burned.set_zero() &&
fees_imported.validate_unpack(std::move(f1.r2.fees_imported)) &&
recovered.validate_unpack(std::move(f1.r2.recovered)) && created.validate_unpack(std::move(f1.r2.created)) &&
minted.validate_unpack(std::move(f1.r2.minted))) {
return true;
}
block::gen::ValueFlow::Record_value_flow_v2 f2;
if (tag == block::gen::ValueFlow::cons_tag[block::gen::ValueFlow::value_flow_v2] && tlb::unpack(cs, f2) &&
from_prev_blk.validate_unpack(std::move(f2.r1.from_prev_blk)) &&
to_next_blk.validate_unpack(std::move(f2.r1.to_next_blk)) &&
imported.validate_unpack(std::move(f2.r1.imported)) && exported.validate_unpack(std::move(f2.r1.exported)) &&
fees_collected.validate_unpack(std::move(f2.fees_collected)) &&
burned.validate_unpack(std::move(f2.burned)) &&
fees_imported.validate_unpack(std::move(f2.r2.fees_imported)) &&
recovered.validate_unpack(std::move(f2.r2.recovered)) && created.validate_unpack(std::move(f2.r2.created)) &&
minted.validate_unpack(std::move(f2.r2.minted))) {
return true;
}
return invalidate();
} }
bool ValueFlow::unpack(Ref<vm::CellSlice> csr) { bool ValueFlow::unpack(Ref<vm::CellSlice> csr) {
@ -1424,7 +1443,8 @@ bool ValueFlow::show(std::ostream& os) const {
show_one(os, " to_next_blk:", to_next_blk) && show_one(os, " imported:", imported) && show_one(os, " to_next_blk:", to_next_blk) && show_one(os, " imported:", imported) &&
show_one(os, " exported:", exported) && show_one(os, " fees_collected:", fees_collected) && show_one(os, " exported:", exported) && show_one(os, " fees_collected:", fees_collected) &&
show_one(os, " fees_imported:", fees_imported) && show_one(os, " recovered:", recovered) && show_one(os, " fees_imported:", fees_imported) && show_one(os, " recovered:", recovered) &&
show_one(os, " created:", created) && show_one(os, " minted:", minted) && say(os, ")")) || show_one(os, " created:", created) && show_one(os, " minted:", minted) &&
(burned.is_zero() || show_one(os, " burned:", burned)) && say(os, ")")) ||
(say(os, "...<invalid-value-flow>)") && false); (say(os, "...<invalid-value-flow>)") && false);
} }

View file

@ -456,7 +456,7 @@ struct ShardState {
struct ValueFlow { struct ValueFlow {
struct SetZero {}; struct SetZero {};
CurrencyCollection from_prev_blk, to_next_blk, imported, exported, fees_collected, fees_imported, recovered, created, CurrencyCollection from_prev_blk, to_next_blk, imported, exported, fees_collected, fees_imported, recovered, created,
minted; minted, burned;
ValueFlow() = default; ValueFlow() = default;
ValueFlow(SetZero) ValueFlow(SetZero)
: from_prev_blk{0} : from_prev_blk{0}
@ -467,7 +467,8 @@ struct ValueFlow {
, fees_imported{0} , fees_imported{0}
, recovered{0} , recovered{0}
, created{0} , created{0}
, minted{0} { , minted{0}
, burned{0} {
} }
bool is_valid() const { bool is_valid() const {
return from_prev_blk.is_valid() && minted.is_valid(); return from_prev_blk.is_valid() && minted.is_valid();

View file

@ -472,6 +472,19 @@ value_flow#b8e48dfb ^[ from_prev_blk:CurrencyCollection
minted:CurrencyCollection minted:CurrencyCollection
] = ValueFlow; ] = ValueFlow;
value_flow_v2#3ebf98b7 ^[ from_prev_blk:CurrencyCollection
to_next_blk:CurrencyCollection
imported:CurrencyCollection
exported:CurrencyCollection ]
fees_collected:CurrencyCollection
burned:CurrencyCollection
^[
fees_imported:CurrencyCollection
recovered:CurrencyCollection
created:CurrencyCollection
minted:CurrencyCollection
] = ValueFlow;
// //
// //
bt_leaf$0 {X:Type} leaf:X = BinTree X; bt_leaf$0 {X:Type} leaf:X = BinTree X;
@ -595,6 +608,11 @@ _ minter_addr:bits256 = ConfigParam 2; // ConfigParam 0 is used if absent
_ fee_collector_addr:bits256 = ConfigParam 3; // ConfigParam 1 is used if absent _ fee_collector_addr:bits256 = ConfigParam 3; // ConfigParam 1 is used if absent
_ dns_root_addr:bits256 = ConfigParam 4; // root TON DNS resolver _ dns_root_addr:bits256 = ConfigParam 4; // root TON DNS resolver
burning_config#01
blackhole_addr:(Maybe bits256)
fee_burn_nom:# fee_burn_denom:# { fee_burn_nom <= fee_burn_denom } { fee_burn_denom >= 1 } = BurningConfig;
_ BurningConfig = ConfigParam 5;
_ mint_new_price:Grams mint_add_price:Grams = ConfigParam 6; _ mint_new_price:Grams mint_add_price:Grams = ConfigParam 6;
_ to_mint:ExtraCurrencyCollection = ConfigParam 7; _ to_mint:ExtraCurrencyCollection = ConfigParam 7;

View file

@ -855,11 +855,12 @@ Ref<McShardHash> McShardHash::from_block(Ref<vm::Cell> block_root, const ton::Fi
ton::RootHash rhash = block_root->get_hash().bits(); ton::RootHash rhash = block_root->get_hash().bits();
CurrencyCollection fees_collected, funds_created; CurrencyCollection fees_collected, funds_created;
if (init_fees) { if (init_fees) {
block::gen::ValueFlow::Record flow; block::ValueFlow flow;
if (!(tlb::unpack_cell(rec.value_flow, flow) && fees_collected.unpack(flow.fees_collected) && if (!flow.unpack(vm::load_cell_slice_ref(rec.value_flow))) {
funds_created.unpack(flow.r2.created))) {
return {}; return {};
} }
fees_collected = flow.fees_collected;
funds_created = flow.created;
} }
return Ref<McShardHash>(true, ton::BlockId{ton::ShardIdFull(shard), (unsigned)info.seq_no}, info.start_lt, return Ref<McShardHash>(true, ton::BlockId{ton::ShardIdFull(shard), (unsigned)info.seq_no}, info.start_lt,
info.end_lt, info.gen_utime, rhash, fhash, fees_collected, funds_created, ~0U, info.end_lt, info.gen_utime, rhash, fhash, fees_collected, funds_created, ~0U,
@ -909,11 +910,12 @@ Ref<McShardDescr> McShardDescr::from_block(Ref<vm::Cell> block_root, Ref<vm::Cel
ton::RootHash rhash = block_root->get_hash().bits(); ton::RootHash rhash = block_root->get_hash().bits();
CurrencyCollection fees_collected, funds_created; CurrencyCollection fees_collected, funds_created;
if (init_fees) { if (init_fees) {
block::gen::ValueFlow::Record flow; block::ValueFlow flow;
if (!(tlb::unpack_cell(rec.value_flow, flow) && fees_collected.unpack(flow.fees_collected) && if (!flow.unpack(vm::load_cell_slice_ref(rec.value_flow))) {
funds_created.unpack(flow.r2.created))) {
return {}; return {};
} }
fees_collected = flow.fees_collected;
funds_created = flow.created;
} }
auto res = Ref<McShardDescr>(true, ton::BlockId{ton::ShardIdFull(shard), (unsigned)info.seq_no}, info.start_lt, auto res = Ref<McShardDescr>(true, ton::BlockId{ton::ShardIdFull(shard), (unsigned)info.seq_no}, info.start_lt,
info.end_lt, info.gen_utime, rhash, fhash, fees_collected, funds_created, ~0U, info.end_lt, info.gen_utime, rhash, fhash, fees_collected, funds_created, ~0U,
@ -1954,6 +1956,24 @@ std::unique_ptr<vm::Dictionary> Config::get_suspended_addresses(ton::UnixTime no
return std::make_unique<vm::Dictionary>(rec.addresses->prefetch_ref(), 288); return std::make_unique<vm::Dictionary>(rec.addresses->prefetch_ref(), 288);
} }
BurningConfig Config::get_burning_config() const {
td::Ref<vm::Cell> param = get_config_param(5);
gen::BurningConfig::Record rec;
if (param.is_null() || !tlb::unpack_cell(param, rec)) {
return {};
}
BurningConfig c;
c.fee_burn_nom = rec.fee_burn_nom;
c.fee_burn_denom = rec.fee_burn_denom;
vm::CellSlice& addr = rec.blackhole_addr.write();
if (addr.fetch_long(1)) {
td::Bits256 x;
addr.fetch_bits_to(x.bits(), 256);
c.blackhole_addr = x;
}
return c;
}
td::Result<std::pair<ton::UnixTime, ton::UnixTime>> Config::unpack_validator_set_start_stop(Ref<vm::Cell> vset_root) { td::Result<std::pair<ton::UnixTime, ton::UnixTime>> Config::unpack_validator_set_start_stop(Ref<vm::Cell> vset_root) {
if (vset_root.is_null()) { if (vset_root.is_null()) {
return td::Status::Error("validator set absent"); return td::Status::Error("validator set absent");

View file

@ -504,6 +504,22 @@ class ShardConfig {
bool set_shard_info(ton::ShardIdFull shard, Ref<vm::Cell> value); bool set_shard_info(ton::ShardIdFull shard, Ref<vm::Cell> value);
}; };
struct BurningConfig {
td::optional<td::Bits256> blackhole_addr;
td::uint32 fee_burn_nom = 0, fee_burn_denom = 1;
td::RefInt256 calculate_burned_fees(const td::RefInt256& x) const {
if (x.is_null()) {
return x;
}
return x * fee_burn_nom / td::make_refint(fee_burn_denom);
}
CurrencyCollection calculate_burned_fees(const CurrencyCollection& x) const {
return CurrencyCollection{calculate_burned_fees(x.grams)};
}
};
class Config { class Config {
enum { enum {
default_mc_catchain_lifetime = 200, default_mc_catchain_lifetime = 200,
@ -617,6 +633,7 @@ class Config {
std::vector<ton::ValidatorDescr> compute_total_validator_set(int next) const; std::vector<ton::ValidatorDescr> compute_total_validator_set(int next) const;
td::Result<SizeLimitsConfig> get_size_limits_config() const; td::Result<SizeLimitsConfig> get_size_limits_config() const;
std::unique_ptr<vm::Dictionary> get_suspended_addresses(ton::UnixTime now) const; std::unique_ptr<vm::Dictionary> get_suspended_addresses(ton::UnixTime now) const;
BurningConfig get_burning_config() const;
static std::vector<ton::ValidatorDescr> do_compute_validator_set(const block::CatchainValidatorsConfig& ccv_conf, static std::vector<ton::ValidatorDescr> do_compute_validator_set(const block::CatchainValidatorsConfig& ccv_conf,
ton::ShardIdFull shard, ton::ShardIdFull shard,
const block::ValidatorSet& vset, ton::UnixTime time, const block::ValidatorSet& vset, ton::UnixTime time,

View file

@ -672,6 +672,12 @@ bool Transaction::unpack_input_msg(bool ihr_delivered, const ActionPhaseConfig*
return false; return false;
} }
total_fees += in_fwd_fee; total_fees += in_fwd_fee;
if (account.workchain == ton::masterchainId && cfg->mc_blackhole_addr &&
cfg->mc_blackhole_addr.value() == account.addr) {
blackhole_burned.grams = msg_balance_remaining.grams;
msg_balance_remaining.grams = td::zero_refint();
LOG(DEBUG) << "Burning " << blackhole_burned.grams << " nanoton (blackhole address)";
}
return true; return true;
} }
@ -2618,6 +2624,7 @@ td::Status FetchConfigParams::fetch_config_params(const block::Config& config,
action_phase_cfg->workchains = &config.get_workchain_list(); action_phase_cfg->workchains = &config.get_workchain_list();
action_phase_cfg->bounce_msg_body = (config.has_capability(ton::capBounceMsgBody) ? 256 : 0); action_phase_cfg->bounce_msg_body = (config.has_capability(ton::capBounceMsgBody) ? 256 : 0);
action_phase_cfg->size_limits = size_limits; action_phase_cfg->size_limits = size_limits;
action_phase_cfg->mc_blackhole_addr = config.get_burning_config().blackhole_addr;
} }
{ {
// fetch block_grams_created // fetch block_grams_created

View file

@ -153,6 +153,7 @@ struct ActionPhaseConfig {
MsgPrices fwd_mc; // from/to masterchain MsgPrices fwd_mc; // from/to masterchain
SizeLimitsConfig size_limits; SizeLimitsConfig size_limits;
const WorkchainSet* workchains{nullptr}; const WorkchainSet* workchains{nullptr};
td::optional<td::Bits256> mc_blackhole_addr;
const MsgPrices& fetch_msg_prices(bool is_masterchain) const { const MsgPrices& fetch_msg_prices(bool is_masterchain) const {
return is_masterchain ? fwd_mc : fwd_std; return is_masterchain ? fwd_mc : fwd_std;
} }
@ -332,6 +333,7 @@ struct Transaction {
td::RefInt256 due_payment; td::RefInt256 due_payment;
td::RefInt256 in_fwd_fee, msg_fwd_fees; td::RefInt256 in_fwd_fee, msg_fwd_fees;
block::CurrencyCollection total_fees{0}; block::CurrencyCollection total_fees{0};
block::CurrencyCollection blackhole_burned{0};
ton::UnixTime last_paid; ton::UnixTime last_paid;
Ref<vm::Cell> root; Ref<vm::Cell> root;
Ref<vm::Cell> new_total_state; Ref<vm::Cell> new_total_state;

View file

@ -1998,7 +1998,7 @@ TypeExpr* parse_anonymous_constructor(Lexer& lex, Constructor& cs) {
if (types[i].parent_type_idx >= 0) { if (types[i].parent_type_idx >= 0) {
types[i].parent_type_idx = -2; types[i].parent_type_idx = -2;
} }
delete cs2; cs2->~Constructor();
return TypeExpr::mk_apply_empty(lex.cur().loc, 0, &types[i]); return TypeExpr::mk_apply_empty(lex.cur().loc, 0, &types[i]);
} }
} }

View file

@ -3,11 +3,11 @@
"flake-compat": { "flake-compat": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1650374568, "lastModified": 1673956053,
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra", "owner": "edolstra",
"repo": "flake-compat", "repo": "flake-compat",
"rev": "b4a34015c698c7793d592d66adbab377907a2be8", "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -17,12 +17,15 @@
} }
}, },
"flake-utils": { "flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": { "locked": {
"lastModified": 1652776076, "lastModified": 1681202837,
"narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -33,11 +36,11 @@
}, },
"nixpkgs-stable": { "nixpkgs-stable": {
"locked": { "locked": {
"lastModified": 1659445012, "lastModified": 1682600000,
"narHash": "sha256-n8/7npmp3hLbPSTRHPW8EPO8qh9vJ10RgkRM3Ve4vfc=", "narHash": "sha256-ha4BehR1dh8EnXSoE1m/wyyYVvHI9txjW4w5/oxsW5Y=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "a9f66ae640146ac16b6e33d2359e9171b27b0993", "rev": "50fc86b75d2744e1ab3837ef74b53f103a9b55a0",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -49,11 +52,11 @@
}, },
"nixpkgs-trunk": { "nixpkgs-trunk": {
"locked": { "locked": {
"lastModified": 1659597264, "lastModified": 1683098912,
"narHash": "sha256-aI/r4XEZwMJnuDjIMnSiDm34vVXP6TPaWgqPIF/65SI=", "narHash": "sha256-bFHOixPoHZ5y44FvFgpEuZV0UYTQPNDZK/XqeUi1Lbs=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "2b22614150a727a8aeedc10395dbd2ff6430841b", "rev": "abc97d3572dec126eba9fec358eb2f359a944683",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -69,6 +72,21 @@
"nixpkgs-stable": "nixpkgs-stable", "nixpkgs-stable": "nixpkgs-stable",
"nixpkgs-trunk": "nixpkgs-trunk" "nixpkgs-trunk": "nixpkgs-trunk"
} }
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View file

@ -31,12 +31,16 @@
openssl_1_1 openssl_1_1
zlib zlib
libmicrohttpd libmicrohttpd
] else ] else [
[
(openssl_1_1.override { static = true; }).dev (openssl_1_1.override { static = true; }).dev
(zlib.override { shared = false; }).dev (zlib.override { shared = false; }).dev
pkgsStatic.libmicrohttpd.dev ]
] ++ optional staticGlibc glibc.static; ++ optionals (!stdenv.isDarwin) [ pkgsStatic.libmicrohttpd.dev ]
++ optionals stdenv.isDarwin [ (libiconv.override { enableStatic = true; enableShared = false; }) ]
++ optionals stdenv.isDarwin (forEach [ libmicrohttpd.dev gmp.dev nettle.dev (gnutls.override { withP11-kit = false; }).dev libtasn1.dev libidn2.dev libunistring.dev gettext ] (x: x.overrideAttrs(oldAttrs: rec { configureFlags = (oldAttrs.configureFlags or []) ++ [ "--enable-static" "--disable-shared" ]; dontDisableStatic = true; })))
++ optionals staticGlibc [ glibc.static ];
dontAddStaticConfigureFlags = stdenv.isDarwin;
cmakeFlags = [ "-DTON_USE_ABSEIL=OFF" "-DNIX=ON" ] ++ optionals staticMusl [ cmakeFlags = [ "-DTON_USE_ABSEIL=OFF" "-DNIX=ON" ] ++ optionals staticMusl [
"-DCMAKE_CROSSCOMPILING=OFF" # pkgsStatic sets cross "-DCMAKE_CROSSCOMPILING=OFF" # pkgsStatic sets cross
@ -47,6 +51,7 @@
LDFLAGS = optional staticExternalDeps (concatStringsSep " " [ LDFLAGS = optional staticExternalDeps (concatStringsSep " " [
(optionalString stdenv.cc.isGNU "-static-libgcc") (optionalString stdenv.cc.isGNU "-static-libgcc")
(optionalString stdenv.isDarwin "-framework CoreFoundation")
"-static-libstdc++" "-static-libstdc++"
]); ]);
@ -57,6 +62,14 @@
moveToOutput bin "$bin" moveToOutput bin "$bin"
''; '';
preFixup = optionalString stdenv.isDarwin ''
for fn in "$bin"/bin/* "$out"/lib/*.dylib; do
echo Fixing libc++ in "$fn"
install_name_tool -change "$(otool -L "$fn" | grep libc++.1 | cut -d' ' -f1 | xargs)" libc++.1.dylib "$fn"
install_name_tool -change "$(otool -L "$fn" | grep libc++abi.1 | cut -d' ' -f1 | xargs)" libc++abi.dylib "$fn"
done
'';
outputs = [ "bin" "out" ]; outputs = [ "bin" "out" ];
}; };
hostPkgs = system: hostPkgs = system:
@ -131,7 +144,7 @@
}; };
ton-staticbin-dylib = host.symlinkJoin { ton-staticbin-dylib = host.symlinkJoin {
name = "ton"; name = "ton";
paths = [ ton-static.bin ton-normal.out ]; paths = [ ton-static.bin ton-static.out ];
}; };
}; };
devShells.default = devShells.default =

View file

@ -1,8 +1,5 @@
## 2023.05 Update ## 2023.06 Update
1. Archive manager optimization 1. (disabled by default) New deflation mechanisms: partial fee burning and blackhole address
2. A series of catchain (basic consensus protocol) security improvements 2. Storage-contract improvement
3. Update for Fift libraries and FunC: better error-handling, fixes for `catch` stack recovery
4. A series of out message queue handling optimization (already deployed during emergency upgrades between releases)
5. Improvement of binaries portability
Besides the work of the core team, this update is based on the efforts of @aleksej-paschenko (portability improvement), [Disintar team](https://github.com/disintar/) (archive manager optimization) and [sec3-service](https://github.com/sec3-service) security auditors (funC improvements). Besides the work of the core team, this update is based on the efforts of @DearJohnDoe from Tonbyte (Storage-contract improvement).

View file

@ -2,7 +2,7 @@
#include "constants.fc"; #include "constants.fc";
const min_deploy_amount = 50000000; const min_deploy_amount = 60000000;
;; cell storage_contract_code() asm """ "storage-contract-code.boc" file>B B>boc PUSHREF """; ;; cell storage_contract_code() asm """ "storage-contract-code.boc" file>B B>boc PUSHREF """;
;; the same constant but more "compiler" friendly ;; the same constant but more "compiler" friendly

View file

@ -143,7 +143,7 @@ PROGRAM{
IFJMP:<{ // msg_value sender_address op query_id in_msg_body IFJMP:<{ // msg_value sender_address op query_id in_msg_body
s2 POP // msg_value sender_address in_msg_body query_id s2 POP // msg_value sender_address in_msg_body query_id
s0 s3 XCHG s0 s3 XCHG
50000000 PUSHINT // query_id sender_address in_msg_body msg_value _29=50000000 60000000 PUSHINT // query_id sender_address in_msg_body msg_value _29=60000000
GEQ // query_id sender_address in_msg_body _30 GEQ // query_id sender_address in_msg_body _30
1001 THROWIFNOT 1001 THROWIFNOT
LDREF // query_id sender_address torrent_info in_msg_body LDREF // query_id sender_address torrent_info in_msg_body

View file

@ -1393,7 +1393,13 @@ bool Collator::import_new_shard_top_blocks() {
} }
LOG(INFO) << "total fees_imported = " << value_flow_.fees_imported.to_str() LOG(INFO) << "total fees_imported = " << value_flow_.fees_imported.to_str()
<< " ; out of them, total fees_created = " << import_created_.to_str(); << " ; out of them, total fees_created = " << import_created_.to_str();
value_flow_.fees_collected += value_flow_.fees_imported; block::CurrencyCollection burned =
config_->get_burning_config().calculate_burned_fees(value_flow_.fees_imported - import_created_);
if (!burned.is_valid()) {
return fatal_error("cannot calculate amount of burned imported fees");
}
value_flow_.burned += burned;
value_flow_.fees_collected += value_flow_.fees_imported - burned;
return true; return true;
} }
@ -2208,6 +2214,7 @@ Ref<vm::Cell> Collator::create_ordinary_transaction(Ref<vm::Cell> msg_root) {
register_new_msgs(*trans); register_new_msgs(*trans);
update_max_lt(acc->last_trans_end_lt_); update_max_lt(acc->last_trans_end_lt_);
value_flow_.burned += trans->blackhole_burned;
return trans_root; return trans_root;
} }
@ -3733,7 +3740,16 @@ bool Collator::compute_total_balance() {
LOG(ERROR) << "cannot unpack CurrencyCollection from the root of OutMsgDescr"; LOG(ERROR) << "cannot unpack CurrencyCollection from the root of OutMsgDescr";
return false; return false;
} }
value_flow_.fees_collected += new_transaction_fees + new_import_fees; block::CurrencyCollection total_fees = new_transaction_fees + new_import_fees;
value_flow_.fees_collected += total_fees;
if (is_masterchain()) {
block::CurrencyCollection burned = config_->get_burning_config().calculate_burned_fees(total_fees);
if (!burned.is_valid()) {
return fatal_error("cannot calculate amount of burned masterchain fees");
}
value_flow_.fees_collected -= burned;
value_flow_.burned += burned;
}
// 3. compute total_validator_fees // 3. compute total_validator_fees
total_validator_fees_ += value_flow_.fees_collected; total_validator_fees_ += value_flow_.fees_collected;
total_validator_fees_ -= value_flow_.recovered; total_validator_fees_ -= value_flow_.recovered;

View file

@ -62,12 +62,10 @@ td::Status ShardTopBlockDescrQ::unpack_one_proof(BlockIdExt& cur_id, Ref<vm::Cel
block::gen::Block::Record blk; block::gen::Block::Record blk;
block::gen::BlockInfo::Record info; block::gen::BlockInfo::Record info;
block::gen::BlockExtra::Record extra; block::gen::BlockExtra::Record extra;
block::gen::ValueFlow::Record flow; block::ValueFlow flow;
block::CurrencyCollection fees_collected, funds_created;
if (!(tlb::unpack_cell(virt_root, blk) && tlb::unpack_cell(blk.info, info) && !info.version && if (!(tlb::unpack_cell(virt_root, blk) && tlb::unpack_cell(blk.info, info) && !info.version &&
block::gen::t_ValueFlow.force_validate_ref(blk.value_flow) && tlb::unpack_cell(blk.value_flow, flow) && flow.unpack(vm::load_cell_slice_ref(blk.value_flow)))
/*tlb::unpack_cell(blk.extra, extra) &&*/ fees_collected.unpack(flow.fees_collected) && /*&& tlb::unpack_cell(blk.extra, extra)*/) {
funds_created.unpack(flow.r2.created))) {
return td::Status::Error(-666, "cannot unpack block header in link for block "s + cur_id.to_str()); return td::Status::Error(-666, "cannot unpack block header in link for block "s + cur_id.to_str());
} }
// remove this "try ... catch ..." later and uncomment tlb::unpack_cell(blk.extra, extra) in the previous condition // remove this "try ... catch ..." later and uncomment tlb::unpack_cell(blk.extra, extra) in the previous condition
@ -131,7 +129,7 @@ td::Status ShardTopBlockDescrQ::unpack_one_proof(BlockIdExt& cur_id, Ref<vm::Cel
} }
chain_mc_blk_ids_.push_back(mc_blkid); chain_mc_blk_ids_.push_back(mc_blkid);
chain_blk_ids_.push_back(cur_id); chain_blk_ids_.push_back(cur_id);
chain_fees_.emplace_back(std::move(fees_collected), std::move(funds_created)); chain_fees_.emplace_back(std::move(flow.fees_collected), std::move(flow.created));
creators_.push_back(extra.created_by); creators_.push_back(extra.created_by);
if (!is_head) { if (!is_head) {
if (info.after_split || info.after_merge) { if (info.after_split || info.after_merge) {

View file

@ -808,6 +808,7 @@ bool ValidateQuery::fetch_config_params() {
action_phase_cfg_.workchains = &config_->get_workchain_list(); action_phase_cfg_.workchains = &config_->get_workchain_list();
action_phase_cfg_.bounce_msg_body = (config_->has_capability(ton::capBounceMsgBody) ? 256 : 0); action_phase_cfg_.bounce_msg_body = (config_->has_capability(ton::capBounceMsgBody) ? 256 : 0);
action_phase_cfg_.size_limits = size_limits; action_phase_cfg_.size_limits = size_limits;
action_phase_cfg_.mc_blackhole_addr = config_->get_burning_config().blackhole_addr;
} }
{ {
// fetch block_grams_created // fetch block_grams_created
@ -2161,6 +2162,11 @@ bool ValidateQuery::unpack_precheck_value_flow(Ref<vm::Cell> value_flow_root) {
return reject_query("ValueFlow of block "s + id_.to_str() + return reject_query("ValueFlow of block "s + id_.to_str() +
" is invalid (non-zero recovered value in a non-masterchain block)"); " is invalid (non-zero recovered value in a non-masterchain block)");
} }
if (!is_masterchain() && !value_flow_.burned.is_zero()) {
LOG(INFO) << "invalid value flow: " << os.str();
return reject_query("ValueFlow of block "s + id_.to_str() +
" is invalid (non-zero burned value in a non-masterchain block)");
}
if (!value_flow_.recovered.is_zero() && recover_create_msg_.is_null()) { if (!value_flow_.recovered.is_zero() && recover_create_msg_.is_null()) {
return reject_query("ValueFlow of block "s + id_.to_str() + return reject_query("ValueFlow of block "s + id_.to_str() +
" has a non-zero recovered fees value, but there is no recovery InMsg"); " has a non-zero recovered fees value, but there is no recovery InMsg");
@ -2243,15 +2249,10 @@ bool ValidateQuery::unpack_precheck_value_flow(Ref<vm::Cell> value_flow_root) {
"cannot unpack CurrencyCollection with total transaction fees from the augmentation of the ShardAccountBlocks " "cannot unpack CurrencyCollection with total transaction fees from the augmentation of the ShardAccountBlocks "
"dictionary"); "dictionary");
} }
auto expected_fees = value_flow_.fees_imported + value_flow_.created + transaction_fees_ + import_fees_; if (is_masterchain()) {
if (value_flow_.fees_collected != expected_fees) { auto x = config_->get_burning_config().calculate_burned_fees(transaction_fees_ + import_fees_);
return reject_query(PSTRING() << "ValueFlow for " << id_.to_str() << " declares fees_collected=" fees_burned_ += x;
<< value_flow_.fees_collected.to_str() << " but the total message import fees are " total_burned_ += x;
<< import_fees_ << ", the total transaction fees are " << transaction_fees_.to_str()
<< ", creation fee for this block is " << value_flow_.created.to_str()
<< " and the total imported fees from shards are "
<< value_flow_.fees_imported.to_str() << " with a total of "
<< expected_fees.to_str());
} }
return true; return true;
} }
@ -4564,6 +4565,7 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT
<< "transaction " << lt << " of " << addr.to_hex() << "transaction " << lt << " of " << addr.to_hex()
<< " is invalid: it has produced a set of outbound messages different from that listed in the transaction"); << " is invalid: it has produced a set of outbound messages different from that listed in the transaction");
} }
total_burned_ += trs->blackhole_burned;
// check new balance and value flow // check new balance and value flow
auto new_balance = account.get_balance(); auto new_balance = account.get_balance();
block::CurrencyCollection total_fees; block::CurrencyCollection total_fees;
@ -4571,12 +4573,14 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT
return reject_query(PSTRING() << "transaction " << lt << " of " << addr.to_hex() return reject_query(PSTRING() << "transaction " << lt << " of " << addr.to_hex()
<< " has an invalid total_fees value"); << " has an invalid total_fees value");
} }
if (old_balance + money_imported != new_balance + money_exported + total_fees) { if (old_balance + money_imported != new_balance + money_exported + total_fees + trs->blackhole_burned) {
return reject_query(PSTRING() << "transaction " << lt << " of " << addr.to_hex() return reject_query(
<< " violates the currency flow condition: old balance=" << old_balance.to_str() PSTRING() << "transaction " << lt << " of " << addr.to_hex()
<< " + imported=" << money_imported.to_str() << " does not equal new balance=" << " violates the currency flow condition: old balance=" << old_balance.to_str()
<< new_balance.to_str() << " + exported=" << money_exported.to_str() << " + imported=" << money_imported.to_str() << " does not equal new balance=" << new_balance.to_str()
<< " + total_fees=" << total_fees.to_str()); << " + exported=" << money_exported.to_str() << " + total_fees=" << total_fees.to_str()
<< (trs->blackhole_burned.is_zero() ? ""
: PSTRING() << " burned=" << trs->blackhole_burned.to_str()));
} }
return true; return true;
} }
@ -5447,6 +5451,9 @@ bool ValidateQuery::check_mc_block_extra() {
return reject_query("invalid fees_imported in value flow: declared "s + value_flow_.fees_imported.to_str() + return reject_query("invalid fees_imported in value flow: declared "s + value_flow_.fees_imported.to_str() +
", correct value is " + fees_imported.to_str()); ", correct value is " + fees_imported.to_str());
} }
auto x = config_->get_burning_config().calculate_burned_fees(fees_imported - import_created_);
total_burned_ += x;
fees_burned_ += x;
// ^[ prev_blk_signatures:(HashmapE 16 CryptoSignaturePair) // ^[ prev_blk_signatures:(HashmapE 16 CryptoSignaturePair)
if (prev_signatures_.not_null() && id_.seqno() == 1) { if (prev_signatures_.not_null() && id_.seqno() == 1) {
return reject_query("block contains non-empty signature set for the zero state of the masterchain"); return reject_query("block contains non-empty signature set for the zero state of the masterchain");
@ -5464,6 +5471,26 @@ bool ValidateQuery::check_mc_block_extra() {
return true; return true;
} }
bool ValidateQuery::postcheck_value_flow() {
auto expected_fees =
value_flow_.fees_imported + value_flow_.created + transaction_fees_ + import_fees_ - fees_burned_;
if (value_flow_.fees_collected != expected_fees) {
return reject_query(PSTRING() << "ValueFlow for " << id_.to_str() << " declares fees_collected="
<< value_flow_.fees_collected.to_str() << " but the total message import fees are "
<< import_fees_ << ", the total transaction fees are " << transaction_fees_.to_str()
<< ", creation fee for this block is " << value_flow_.created.to_str()
<< ", the total imported fees from shards are " << value_flow_.fees_imported.to_str()
<< " and the burned fees are " << fees_burned_.to_str()
<< " with a total of " << expected_fees.to_str());
}
if (total_burned_ != value_flow_.burned) {
return reject_query(PSTRING() << "invalid burned in value flow: " << id_.to_str() << " declared "
<< value_flow_.burned.to_str() << ", correct value is "
<< total_burned_.to_str());
}
return true;
}
/* /*
* *
* MAIN VALIDATOR FUNCTION * MAIN VALIDATOR FUNCTION
@ -5565,6 +5592,9 @@ bool ValidateQuery::try_validate() {
if (!check_mc_state_extra()) { if (!check_mc_state_extra()) {
return reject_query("new McStateExtra is invalid"); return reject_query("new McStateExtra is invalid");
} }
if (!postcheck_value_flow()) {
return reject_query("new ValueFlow is invalid");
}
} catch (vm::VmError& err) { } catch (vm::VmError& err) {
return fatal_error(-666, err.get_msg()); return fatal_error(-666, err.get_msg());
} catch (vm::VmVirtError& err) { } catch (vm::VmVirtError& err) {

View file

@ -217,7 +217,7 @@ class ValidateQuery : public td::actor::Actor {
std::unique_ptr<vm::AugmentedDictionary> in_msg_dict_, out_msg_dict_, account_blocks_dict_; std::unique_ptr<vm::AugmentedDictionary> in_msg_dict_, out_msg_dict_, account_blocks_dict_;
block::ValueFlow value_flow_; block::ValueFlow value_flow_;
block::CurrencyCollection import_created_, transaction_fees_; block::CurrencyCollection import_created_, transaction_fees_, total_burned_{0}, fees_burned_{0};
td::RefInt256 import_fees_; td::RefInt256 import_fees_;
ton::LogicalTime proc_lt_{0}, claimed_proc_lt_{0}, min_enq_lt_{~0ULL}; ton::LogicalTime proc_lt_{0}, claimed_proc_lt_{0}, min_enq_lt_{~0ULL};
@ -361,6 +361,7 @@ class ValidateQuery : public td::actor::Actor {
bool check_one_prev_dict_update(ton::BlockSeqno seqno, Ref<vm::CellSlice> old_val_extra, bool check_one_prev_dict_update(ton::BlockSeqno seqno, Ref<vm::CellSlice> old_val_extra,
Ref<vm::CellSlice> new_val_extra); Ref<vm::CellSlice> new_val_extra);
bool check_mc_state_extra(); bool check_mc_state_extra();
bool postcheck_value_flow();
td::Status check_counter_update(const block::DiscountedCounter& oc, const block::DiscountedCounter& nc, td::Status check_counter_update(const block::DiscountedCounter& oc, const block::DiscountedCounter& nc,
unsigned expected_incr); unsigned expected_incr);
bool check_one_block_creator_update(td::ConstBitPtr key, Ref<vm::CellSlice> old_val, Ref<vm::CellSlice> new_val); bool check_one_block_creator_update(td::ConstBitPtr key, Ref<vm::CellSlice> old_val, Ref<vm::CellSlice> new_val);