1
0
Fork 0
mirror of https://github.com/ton-blockchain/ton synced 2025-03-09 15:40:10 +00:00

New extra currency behavior (#1539)

This commit is contained in:
SpyCheese 2025-02-27 15:18:59 +03:00 committed by GitHub
parent 1b70e48327
commit b3b2bd1c3c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 228 additions and 65 deletions

View file

@ -19,6 +19,6 @@
namespace ton {
// See doc/GlobalVersions.md
const int SUPPORTED_VERSION = 9;
constexpr int SUPPORTED_VERSION = 10;
}

View file

@ -1350,6 +1350,35 @@ bool CurrencyCollection::clamp(const CurrencyCollection& other) {
return ok || invalidate();
}
bool CurrencyCollection::check_extra_currency_limit(td::uint32 max_currencies) const {
td::uint32 count = 0;
return vm::Dictionary{extra, 32}.check_for_each([&](td::Ref<vm::CellSlice>, td::ConstBitPtr, int) {
++count;
return count <= max_currencies;
});
}
bool CurrencyCollection::remove_zero_extra_currencies(Ref<vm::Cell>& root, td::uint32 max_currencies) {
td::uint32 count = 0;
vm::Dictionary dict{root, 32};
int res = dict.filter([&](const vm::CellSlice& cs, td::ConstBitPtr, int) -> int {
++count;
if (count > max_currencies) {
return -1;
}
td::RefInt256 val = tlb::t_VarUInteger_32.as_integer(cs);
if (val.is_null()) {
return -1;
}
return val->sgn() > 0;
});
if (res < 0) {
return false;
}
root = dict.get_root_cell();
return true;
}
bool CurrencyCollection::operator==(const CurrencyCollection& other) const {
return is_valid() && other.is_valid() && !td::cmp(grams, other.grams) &&
(extra.not_null() == other.extra.not_null()) &&

View file

@ -391,6 +391,8 @@ struct CurrencyCollection {
CurrencyCollection operator-(CurrencyCollection&& other) const;
CurrencyCollection operator-(td::RefInt256 other_grams) const;
bool clamp(const CurrencyCollection& other);
bool check_extra_currency_limit(td::uint32 max_currencies) const;
static bool remove_zero_extra_currencies(Ref<vm::Cell>& root, td::uint32 max_currencies);
bool store(vm::CellBuilder& cb) const;
bool store_or_zero(vm::CellBuilder& cb) const;
bool fetch(vm::CellSlice& cs);

View file

@ -801,7 +801,7 @@ size_limits_config#01 max_msg_bits:uint32 max_msg_cells:uint32 max_library_cells
max_ext_msg_size:uint32 max_ext_msg_depth:uint16 = SizeLimitsConfig;
size_limits_config_v2#02 max_msg_bits:uint32 max_msg_cells:uint32 max_library_cells:uint32 max_vm_data_depth:uint16
max_ext_msg_size:uint32 max_ext_msg_depth:uint16 max_acc_state_cells:uint32 max_acc_state_bits:uint32
max_acc_public_libraries:uint32 defer_out_queue_size_limit:uint32 = SizeLimitsConfig;
max_acc_public_libraries:uint32 defer_out_queue_size_limit:uint32 max_msg_extra_currencies:uint32 = SizeLimitsConfig;
_ SizeLimitsConfig = ConfigParam 43;
// key is [ wc:int32 addr:uint256 ]

View file

@ -1960,6 +1960,7 @@ td::Result<SizeLimitsConfig> Config::do_get_size_limits_config(td::Ref<vm::CellS
limits.max_acc_state_cells = rec.max_acc_state_cells;
limits.max_acc_public_libraries = rec.max_acc_public_libraries;
limits.defer_out_queue_size_limit = rec.defer_out_queue_size_limit;
limits.max_msg_extra_currencies = rec.max_msg_extra_currencies;
};
gen::SizeLimitsConfig::Record_size_limits_config rec_v1;
gen::SizeLimitsConfig::Record_size_limits_config_v2 rec_v2;

View file

@ -397,6 +397,7 @@ struct SizeLimitsConfig {
td::uint32 max_acc_state_bits = (1 << 16) * 1023;
td::uint32 max_acc_public_libraries = 256;
td::uint32 defer_out_queue_size_limit = 256;
td::uint32 max_msg_extra_currencies = 2;
};
struct CatchainValidatorsConfig {

View file

@ -2000,9 +2000,9 @@ bool Transaction::prepare_action_phase(const ActionPhaseConfig& cfg) {
ap.remaining_balance += ap.reserved_balance;
CHECK(ap.remaining_balance.is_valid());
if (ap.acc_delete_req) {
CHECK(ap.remaining_balance.is_zero());
CHECK(cfg.extra_currency_v2 ? ap.remaining_balance.grams->sgn() == 0 : ap.remaining_balance.is_zero());
ap.acc_status_change = ActionPhase::acst_deleted;
acc_status = Account::acc_deleted;
acc_status = (ap.remaining_balance.is_zero() ? Account::acc_deleted : Account::acc_uninit);
was_deleted = true;
}
ap.success = true;
@ -2472,6 +2472,20 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
LOG(DEBUG) << "invalid destination address in a proposed outbound message";
return check_skip_invalid(36); // invalid destination address
}
if (cfg.extra_currency_v2) {
CurrencyCollection value;
if (!value.unpack(info.value)) {
LOG(DEBUG) << "invalid value:ExtraCurrencies in a proposed outbound message";
return check_skip_invalid(37); // invalid value:CurrencyCollection
}
if (!CurrencyCollection::remove_zero_extra_currencies(value.extra, cfg.size_limits.max_msg_extra_currencies)) {
LOG(DEBUG) << "invalid value:ExtraCurrencies in a proposed outbound message: too many currencies (max "
<< cfg.size_limits.max_msg_extra_currencies << ")";
// Dict should be valid, since it was checked in t_OutListNode.validate_ref, so error here means limit exceeded
return check_skip_invalid(41); // invalid value:CurrencyCollection : too many extra currencies
}
info.value = value.pack();
}
// fetch message pricing info
const MsgPrices& msg_prices = cfg.fetch_msg_prices(to_mc || account.is_masterchain());
@ -2524,7 +2538,7 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
};
add_used_storage(msg.init, 3); // message init
add_used_storage(msg.body, 3); // message body (the root cell itself is not counted)
if (!ext_msg) {
if (!ext_msg && !cfg.extra_currency_v2) {
add_used_storage(info.value->prefetch_ref(), 0);
}
auto collect_fine = [&] {
@ -2595,11 +2609,19 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
if (act_rec.mode & 0x80) {
// attach all remaining balance to this message
req = ap.remaining_balance;
if (cfg.extra_currency_v2) {
req.grams = ap.remaining_balance.grams;
} else {
req = ap.remaining_balance;
}
act_rec.mode &= ~1; // pay fees from attached value
} else if (act_rec.mode & 0x40) {
// attach all remaining balance of the inbound message (in addition to the original value)
req += msg_balance_remaining;
if (cfg.extra_currency_v2) {
req.grams += msg_balance_remaining.grams;
} else {
req += msg_balance_remaining;
}
if (!(act_rec.mode & 1)) {
req -= ap.action_fine;
if (compute_phase) {
@ -2639,6 +2661,11 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
return check_skip_invalid(37); // not enough grams
}
if (cfg.extra_currency_v2 && !req.check_extra_currency_limit(cfg.size_limits.max_msg_extra_currencies)) {
LOG(DEBUG) << "too many extra currencies in the message : max " << cfg.size_limits.max_msg_extra_currencies;
return check_skip_invalid(41); // to many extra currencies
}
Ref<vm::Cell> new_extra;
if (!block::sub_extra_currency(ap.remaining_balance.extra, req.extra, new_extra)) {
@ -2680,7 +2707,11 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
// clear msg_balance_remaining if it has been used
if (act_rec.mode & 0xc0) {
msg_balance_remaining.set_zero();
if (cfg.extra_currency_v2) {
msg_balance_remaining.grams = td::zero_refint();
} else {
msg_balance_remaining.set_zero();
}
}
// update balance
@ -2754,8 +2785,13 @@ int Transaction::try_action_send_msg(const vm::CellSlice& cs0, ActionPhase& ap,
ap.total_fwd_fees += fees_total;
if ((act_rec.mode & 0xa0) == 0xa0) {
CHECK(ap.remaining_balance.is_zero());
ap.acc_delete_req = ap.reserved_balance.is_zero();
if (cfg.extra_currency_v2) {
CHECK(ap.remaining_balance.grams->sgn() == 0);
ap.acc_delete_req = ap.reserved_balance.grams->sgn() == 0;
} else {
CHECK(ap.remaining_balance.is_zero());
ap.acc_delete_req = ap.reserved_balance.is_zero();
}
}
ap.tot_msg_bits += sstat.bits + new_msg_bits;
@ -3026,7 +3062,8 @@ bool Transaction::prepare_bounce_phase(const ActionPhaseConfig& cfg) {
bp.fwd_fees -= bp.fwd_fees_collected;
total_fees += td::make_refint(bp.fwd_fees_collected);
// serialize outbound message
info.created_lt = end_lt++;
info.created_lt = start_lt + 1 + out_msgs.size();
end_lt++;
info.created_at = now;
vm::CellBuilder cb;
CHECK(cb.store_long_bool(5, 4) // int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool
@ -3107,6 +3144,7 @@ bool Account::store_acc_status(vm::CellBuilder& cb, int acc_status) const {
* Tries to update the storage statistics based on the old storage statistics and old account state without fully recomputing it.
*
* It succeeds if only root cell of AccountStorage is changed.
* old_cs and new_cell are AccountStorage without extra currencies (if global_version >= 10).
*
* @param old_stat The old storage statistics.
* @param old_cs The old AccountStorage.
@ -3140,13 +3178,48 @@ static td::optional<vm::CellStorageStat> try_update_storage_stat(const vm::CellS
return new_stat;
}
/**
* Removes extra currencies dict from AccountStorage.
*
* This is used for computing account storage stats.
*
* @param storage_cs AccountStorage as CellSlice.
*
* @returns AccountStorage without extra currencies as Cell.
*/
static td::Ref<vm::Cell> storage_without_extra_currencies(td::Ref<vm::CellSlice> storage_cs) {
block::gen::AccountStorage::Record rec;
if (!block::gen::csr_unpack(storage_cs, rec)) {
LOG(ERROR) << "failed to unpack AccountStorage";
return {};
}
if (rec.balance->size_refs() > 0) {
block::gen::CurrencyCollection::Record balance;
if (!block::gen::csr_unpack(rec.balance, balance)) {
LOG(ERROR) << "failed to unpack AccountStorage";
return {};
}
balance.other = vm::CellBuilder{}.store_zeroes(1).as_cellslice_ref();
if (!block::gen::csr_pack(rec.balance, balance)) {
LOG(ERROR) << "failed to pack AccountStorage";
return {};
}
}
td::Ref<vm::Cell> cell;
if (!block::gen::pack_cell(cell, rec)) {
LOG(ERROR) << "failed to pack AccountStorage";
return {};
}
return cell;
}
namespace transaction {
/**
* Computes the new state of the account.
*
* @returns True if the state computation is successful, false otherwise.
*/
bool Transaction::compute_state() {
bool Transaction::compute_state(const SerializeConfig& cfg) {
if (new_total_state.not_null()) {
return true;
}
@ -3218,13 +3291,27 @@ bool Transaction::compute_state() {
new_inner_state.clear();
}
vm::CellStorageStat& stats = new_storage_stat;
auto new_stats = try_update_storage_stat(account.storage_stat, account.storage, storage);
td::Ref<vm::CellSlice> old_storage_for_stat = account.storage;
td::Ref<vm::Cell> new_storage_for_stat = storage;
if (cfg.extra_currency_v2) {
new_storage_for_stat = storage_without_extra_currencies(new_storage);
if (new_storage_for_stat.is_null()) {
return false;
}
if (old_storage_for_stat.not_null()) {
old_storage_for_stat = vm::load_cell_slice_ref(storage_without_extra_currencies(old_storage_for_stat));
if (old_storage_for_stat.is_null()) {
return false;
}
}
}
auto new_stats = try_update_storage_stat(account.storage_stat, old_storage_for_stat, storage);
if (new_stats) {
stats = new_stats.unwrap();
} else {
TD_PERF_COUNTER(transaction_storage_stat_b);
td::Timer timer;
stats.add_used_storage(Ref<vm::Cell>(storage)).ensure();
stats.add_used_storage(new_storage_for_stat).ensure();
if (timer.elapsed() > 0.1) {
LOG(INFO) << "Compute used storage took " << timer.elapsed() << "s";
}
@ -3260,11 +3347,11 @@ bool Transaction::compute_state() {
*
* @returns True if the serialization is successful, False otherwise.
*/
bool Transaction::serialize() {
bool Transaction::serialize(const SerializeConfig& cfg) {
if (root.not_null()) {
return true;
}
if (!compute_state()) {
if (!compute_state(cfg)) {
return false;
}
vm::Dictionary dict{15};
@ -3730,6 +3817,7 @@ bool Account::libraries_changed() const {
* @param rand_seed Pointer to the random seed. Generates a new seed if the value is `td::Bits256::zero()`.
* @param compute_phase_cfg Pointer to store the compute phase configuration.
* @param action_phase_cfg Pointer to store the action phase configuration.
* @param serialize_cfg Pointer to store the serialize phase configuration.
* @param masterchain_create_fee Pointer to store the masterchain create fee.
* @param basechain_create_fee Pointer to store the basechain create fee.
* @param wc The workchain ID.
@ -3738,15 +3826,15 @@ bool Account::libraries_changed() const {
td::Status FetchConfigParams::fetch_config_params(
const block::ConfigInfo& config, Ref<vm::Cell>* old_mparams, std::vector<block::StoragePrices>* storage_prices,
StoragePhaseConfig* storage_phase_cfg, td::BitArray<256>* rand_seed, ComputePhaseConfig* compute_phase_cfg,
ActionPhaseConfig* action_phase_cfg, td::RefInt256* masterchain_create_fee, td::RefInt256* basechain_create_fee,
ton::WorkchainId wc, ton::UnixTime now) {
ActionPhaseConfig* action_phase_cfg, SerializeConfig* serialize_cfg, td::RefInt256* masterchain_create_fee,
td::RefInt256* basechain_create_fee, ton::WorkchainId wc, ton::UnixTime now) {
auto prev_blocks_info = config.get_prev_blocks_info();
if (prev_blocks_info.is_error()) {
return prev_blocks_info.move_as_error_prefix(
td::Status::Error(-668, "cannot fetch prev blocks info from masterchain configuration: "));
}
return fetch_config_params(config, prev_blocks_info.move_as_ok(), old_mparams, storage_prices, storage_phase_cfg,
rand_seed, compute_phase_cfg, action_phase_cfg, masterchain_create_fee,
rand_seed, compute_phase_cfg, action_phase_cfg, serialize_cfg, masterchain_create_fee,
basechain_create_fee, wc, now);
}
@ -3761,6 +3849,7 @@ td::Status FetchConfigParams::fetch_config_params(
* @param rand_seed Pointer to the random seed. Generates a new seed if the value is `td::Bits256::zero()`.
* @param compute_phase_cfg Pointer to store the compute phase configuration.
* @param action_phase_cfg Pointer to store the action phase configuration.
* @param serialize_cfg Pointer to store the serialize phase configuration.
* @param masterchain_create_fee Pointer to store the masterchain create fee.
* @param basechain_create_fee Pointer to store the basechain create fee.
* @param wc The workchain ID.
@ -3770,8 +3859,8 @@ td::Status FetchConfigParams::fetch_config_params(
const block::Config& config, td::Ref<vm::Tuple> prev_blocks_info, Ref<vm::Cell>* old_mparams,
std::vector<block::StoragePrices>* storage_prices, StoragePhaseConfig* storage_phase_cfg,
td::BitArray<256>* rand_seed, ComputePhaseConfig* compute_phase_cfg, ActionPhaseConfig* action_phase_cfg,
td::RefInt256* masterchain_create_fee, td::RefInt256* basechain_create_fee, ton::WorkchainId wc,
ton::UnixTime now) {
SerializeConfig* serialize_cfg, td::RefInt256* masterchain_create_fee, td::RefInt256* basechain_create_fee,
ton::WorkchainId wc, ton::UnixTime now) {
*old_mparams = config.get_config_param(9);
{
auto res = config.get_storage_prices();
@ -3843,6 +3932,10 @@ td::Status FetchConfigParams::fetch_config_params(
action_phase_cfg->disable_custom_fess = config.get_global_version() >= 8;
action_phase_cfg->reserve_extra_enabled = config.get_global_version() >= 9;
action_phase_cfg->mc_blackhole_addr = config.get_burning_config().blackhole_addr;
action_phase_cfg->extra_currency_v2 = config.get_global_version() >= 10;
}
{
serialize_cfg->extra_currency_v2 = config.get_global_version() >= 10;
}
{
// fetch block_grams_created

View file

@ -170,12 +170,17 @@ struct ActionPhaseConfig {
bool message_skip_enabled{false};
bool disable_custom_fess{false};
bool reserve_extra_enabled{false};
bool extra_currency_v2{false};
td::optional<td::Bits256> mc_blackhole_addr;
const MsgPrices& fetch_msg_prices(bool is_masterchain) const {
return is_masterchain ? fwd_mc : fwd_std;
}
};
struct SerializeConfig {
bool extra_currency_v2{false};
};
struct CreditPhase {
td::RefInt256 due_fees_collected;
block::CurrencyCollection credit;
@ -389,8 +394,8 @@ struct Transaction {
bool prepare_action_phase(const ActionPhaseConfig& cfg);
td::Status check_state_limits(const SizeLimitsConfig& size_limits, bool update_storage_stat = true);
bool prepare_bounce_phase(const ActionPhaseConfig& cfg);
bool compute_state();
bool serialize();
bool compute_state(const SerializeConfig& cfg);
bool serialize(const SerializeConfig& cfg);
td::uint64 gas_used() const {
return compute_phase ? compute_phase->gas_used : 0;
}
@ -428,14 +433,14 @@ struct FetchConfigParams {
std::vector<block::StoragePrices>* storage_prices,
StoragePhaseConfig* storage_phase_cfg, td::BitArray<256>* rand_seed,
ComputePhaseConfig* compute_phase_cfg, ActionPhaseConfig* action_phase_cfg,
td::RefInt256* masterchain_create_fee, td::RefInt256* basechain_create_fee,
ton::WorkchainId wc, ton::UnixTime now);
SerializeConfig* serialize_cfg, td::RefInt256* masterchain_create_fee,
td::RefInt256* basechain_create_fee, ton::WorkchainId wc, ton::UnixTime now);
static td::Status fetch_config_params(const block::Config& config, Ref<vm::Tuple> prev_blocks_info,
Ref<vm::Cell>* old_mparams, std::vector<block::StoragePrices>* storage_prices,
StoragePhaseConfig* storage_phase_cfg, td::BitArray<256>* rand_seed,
ComputePhaseConfig* compute_phase_cfg, ActionPhaseConfig* action_phase_cfg,
td::RefInt256* masterchain_create_fee, td::RefInt256* basechain_create_fee,
ton::WorkchainId wc, ton::UnixTime now);
SerializeConfig* serialize_cfg, td::RefInt256* masterchain_create_fee,
td::RefInt256* basechain_create_fee, ton::WorkchainId wc, ton::UnixTime now);
};
} // namespace block

View file

@ -1153,8 +1153,12 @@ td::Result<CellStorageStat::CellInfo> CellStorageStat::add_used_storage(Ref<vm::
return ins.first->second;
}
}
vm::CellSlice cs{vm::NoVm{}, std::move(cell)};
return add_used_storage(std::move(cs), kill_dup, skip_count_root);
vm::CellSlice cs{vm::NoVm{}, cell};
TRY_RESULT(res, add_used_storage(std::move(cs), kill_dup, skip_count_root));
if (kill_dup) {
seen[cell->get_hash()] = res;
}
return res;
}
void NewCellStorageStat::add_cell(Ref<Cell> cell) {

View file

@ -1761,6 +1761,10 @@ int exec_send_message(VmState* st) {
vm::VmStorageStat stat(max_cells);
CellSlice cs = load_cell_slice(msg_cell);
cs.skip_first(cs.size());
if (st->get_global_version() >= 10 && have_extra_currencies) {
// Skip extra currency dict
cs.advance_refs(1);
}
stat.add_storage(cs);
if (!ext_msg) {
@ -1773,7 +1777,9 @@ int exec_send_message(VmState* st) {
if (value.is_null()) {
throw VmError{Excno::type_chk, "invalid param BALANCE"};
}
have_extra_currencies |= !tuple_index(balance, 1).as_cell().is_null();
if (st->get_global_version() < 10) {
have_extra_currencies |= !tuple_index(balance, 1).as_cell().is_null();
}
} else if (mode & 64) { // value += value of incoming message
Ref<Tuple> balance = get_param(st, 11).as_tuple();
if (balance.is_null()) {
@ -1784,7 +1790,9 @@ int exec_send_message(VmState* st) {
throw VmError{Excno::type_chk, "invalid param INCOMINGVALUE"};
}
value += balance_grams;
have_extra_currencies |= !tuple_index(balance, 1).as_cell().is_null();
if (st->get_global_version() < 10) {
have_extra_currencies |= !tuple_index(balance, 1).as_cell().is_null();
}
}
}

View file

@ -134,4 +134,25 @@ Example: if the last masterchain block seqno is `19071` then the list contains b
- `PFXDICTADD`, `PFXDICTSET`, `PFXDICTREPLACE`, `PFXDICTDEL`, `GETGASFEE`, `GETSTORAGEFEE`, `GETFORWARDFEE`, `GETORIGINALFWDFEE`, `GETGASFEESIMPLE`, `GETFORWARDFEESIMPLE`, `HASHEXT`
- Now setting the contract code to a library cell does not consume additional gas on execution of the code.
- Temporary increase gas limit for some accounts (see [this post](https://t.me/tondev_news/129) for details, `override_gas_limit` in `transaction.cpp` for the list of accounts).
- Fix recursive jump to continuations with non-null control data.
- Fix recursive jump to continuations with non-null control data.
## Version 10
### Extra currencies
- Internal messages cannot carry more than 2 different extra currencies. The limit can be changed in size limits config (`ConfigParam 43`).
- Amount of an extra currency in an output action "send message" can be zero.
- In action phase zero values are automatically deleted from the dictionary before sending.
- However, the size of the extra currency dictionary in the "send message" action should not be greater than 2 (or the value in size limits config).
- Extra currency dictionary is not counted in message size and does not affect message fees.
- Message mode `+64` (carry all remaining message balance) is now considered as "carry all remaining TONs from message balance".
- Message mode `+128` (carry all remaining account balance) is now considered as "carry all remaining TONs from account balance".
- Message mode `+32` (delete account if balance is zero) deletes account if it has zero TONs, regardless of extra currencies.
- Deleted accounts with extra currencies become `account_uninit`, extra currencies remain on the account.
- `SENDMSG` in TVM calculates message size and fees without extra currencies, uses new `+64` and `+128` mode behavior.
- `SENDMSG` does not check the number of extra currencies.
- Extra currency dictionary is not counted in the account size and does not affect storage fees.
- Accounts with already existing extra currencies will get their sizes recomputed without EC only after modifying `AccountState`.
### TVM changes
- `SENDMSG` calculates messages size and fees without extra currencies, uses new +64 and +128 mode behavior.
- `SENDMSG` does not check the number of extra currencies.

View file

@ -16,6 +16,7 @@ td::Result<std::unique_ptr<TransactionEmulator::EmulationResult>> TransactionEmu
block::StoragePhaseConfig storage_phase_cfg{&storage_prices};
block::ComputePhaseConfig compute_phase_cfg;
block::ActionPhaseConfig action_phase_cfg;
block::SerializeConfig serialize_config;
td::RefInt256 masterchain_create_fee, basechain_create_fee;
if (!utime) {
@ -25,11 +26,9 @@ td::Result<std::unique_ptr<TransactionEmulator::EmulationResult>> TransactionEmu
utime = (unsigned)std::time(nullptr);
}
auto fetch_res = block::FetchConfigParams::fetch_config_params(*config_, prev_blocks_info_, &old_mparams,
&storage_prices, &storage_phase_cfg,
&rand_seed_, &compute_phase_cfg,
&action_phase_cfg, &masterchain_create_fee,
&basechain_create_fee, account.workchain, utime);
auto fetch_res = block::FetchConfigParams::fetch_config_params(
*config_, prev_blocks_info_, &old_mparams, &storage_prices, &storage_phase_cfg, &rand_seed_, &compute_phase_cfg,
&action_phase_cfg, &serialize_config, &masterchain_create_fee, &basechain_create_fee, account.workchain, utime);
if(fetch_res.is_error()) {
return fetch_res.move_as_error_prefix("cannot fetch config params ");
}
@ -66,7 +65,7 @@ td::Result<std::unique_ptr<TransactionEmulator::EmulationResult>> TransactionEmu
return std::make_unique<TransactionEmulator::EmulationExternalNotAccepted>(std::move(vm_log), vm_exit_code, elapsed);
}
if (!trans->serialize()) {
if (!trans->serialize(serialize_config)) {
return td::Status::Error(-669,"cannot serialize new transaction for smart contract "s + trans->account.addr.to_hex());
}

View file

@ -109,14 +109,11 @@ class Collator final : public td::actor::Actor {
return 2;
}
static td::Result<std::unique_ptr<block::transaction::Transaction>>
impl_create_ordinary_transaction(Ref<vm::Cell> msg_root,
block::Account* acc,
UnixTime utime, LogicalTime lt,
block::StoragePhaseConfig* storage_phase_cfg,
block::ComputePhaseConfig* compute_phase_cfg,
block::ActionPhaseConfig* action_phase_cfg,
bool external, LogicalTime after_lt);
static td::Result<std::unique_ptr<block::transaction::Transaction>> impl_create_ordinary_transaction(
Ref<vm::Cell> msg_root, block::Account* acc, UnixTime utime, LogicalTime lt,
block::StoragePhaseConfig* storage_phase_cfg, block::ComputePhaseConfig* compute_phase_cfg,
block::ActionPhaseConfig* action_phase_cfg, block::SerializeConfig* serialize_cfg, bool external,
LogicalTime after_lt);
private:
void start_up() override;
@ -177,6 +174,7 @@ class Collator final : public td::actor::Actor {
block::StoragePhaseConfig storage_phase_cfg_{&storage_prices_};
block::ComputePhaseConfig compute_phase_cfg_;
block::ActionPhaseConfig action_phase_cfg_;
block::SerializeConfig serialize_cfg_;
td::RefInt256 masterchain_create_fee_, basechain_create_fee_;
std::unique_ptr<block::BlockLimits> block_limits_;
std::unique_ptr<block::BlockLimitStatus> block_limit_status_;

View file

@ -1995,12 +1995,9 @@ bool Collator::init_lt() {
* @returns True if the configuration parameters were successfully fetched and initialized, false otherwise.
*/
bool Collator::fetch_config_params() {
auto res = block::FetchConfigParams::fetch_config_params(*config_,
&old_mparams_, &storage_prices_, &storage_phase_cfg_,
&rand_seed_, &compute_phase_cfg_, &action_phase_cfg_,
&masterchain_create_fee_, &basechain_create_fee_,
workchain(), now_
);
auto res = block::FetchConfigParams::fetch_config_params(
*config_, &old_mparams_, &storage_prices_, &storage_phase_cfg_, &rand_seed_, &compute_phase_cfg_,
&action_phase_cfg_, &serialize_cfg_, &masterchain_create_fee_, &basechain_create_fee_, workchain(), now_);
if (res.is_error()) {
return fatal_error(res.move_as_error());
}
@ -2750,7 +2747,7 @@ bool Collator::create_ticktock_transaction(const ton::StdSmcAddress& smc_addr, t
return fatal_error(td::Status::Error(
-666, std::string{"cannot create action phase of a new transaction for smart contract "} + smc_addr.to_hex()));
}
if (!trans->serialize()) {
if (!trans->serialize(serialize_cfg_)) {
return fatal_error(td::Status::Error(
-666, std::string{"cannot serialize new transaction for smart contract "} + smc_addr.to_hex()));
}
@ -2834,7 +2831,7 @@ Ref<vm::Cell> Collator::create_ordinary_transaction(Ref<vm::Cell> msg_root,
after_lt = std::max(after_lt, it->second);
}
auto res = impl_create_ordinary_transaction(msg_root, acc, now_, start_lt, &storage_phase_cfg_, &compute_phase_cfg_,
&action_phase_cfg_, external, after_lt);
&action_phase_cfg_, &serialize_cfg_, external, after_lt);
if (res.is_error()) {
auto error = res.move_as_error();
if (error.code() == -701) {
@ -2885,6 +2882,7 @@ Ref<vm::Cell> Collator::create_ordinary_transaction(Ref<vm::Cell> msg_root,
* @param storage_phase_cfg The configuration for the storage phase of the transaction.
* @param compute_phase_cfg The configuration for the compute phase of the transaction.
* @param action_phase_cfg The configuration for the action phase of the transaction.
* @param serialize_cfg The configuration for the serialization of the transaction.
* @param external Flag indicating if the message is external.
* @param after_lt The logical time after which the transaction should occur. Used only for external messages.
*
@ -2898,6 +2896,7 @@ td::Result<std::unique_ptr<block::transaction::Transaction>> Collator::impl_crea
block::StoragePhaseConfig* storage_phase_cfg,
block::ComputePhaseConfig* compute_phase_cfg,
block::ActionPhaseConfig* action_phase_cfg,
block::SerializeConfig* serialize_cfg,
bool external, LogicalTime after_lt) {
if (acc->last_trans_end_lt_ >= lt && acc->transactions.empty()) {
return td::Status::Error(-669, PSTRING() << "last transaction time in the state of account " << acc->workchain
@ -2965,7 +2964,7 @@ td::Result<std::unique_ptr<block::transaction::Transaction>> Collator::impl_crea
return td::Status::Error(
-669, "cannot create bounce phase of a new transaction for smart contract "s + acc->addr.to_hex());
}
if (!trans->serialize()) {
if (!trans->serialize(*serialize_cfg)) {
return td::Status::Error(-669, "cannot serialize new transaction for smart contract "s + acc->addr.to_hex());
}
return std::move(trans);

View file

@ -136,13 +136,12 @@ td::Status ExtMessageQ::run_message_on_account(ton::WorkchainId wc,
td::BitArray<256> rand_seed_;
block::ComputePhaseConfig compute_phase_cfg_;
block::ActionPhaseConfig action_phase_cfg_;
block::SerializeConfig serialize_config_;
td::RefInt256 masterchain_create_fee, basechain_create_fee;
auto fetch_res = block::FetchConfigParams::fetch_config_params(*config, &old_mparams,
&storage_prices_, &storage_phase_cfg_,
&rand_seed_, &compute_phase_cfg_,
&action_phase_cfg_, &masterchain_create_fee,
&basechain_create_fee, wc, utime);
auto fetch_res = block::FetchConfigParams::fetch_config_params(
*config, &old_mparams, &storage_prices_, &storage_phase_cfg_, &rand_seed_, &compute_phase_cfg_,
&action_phase_cfg_, &serialize_config_, &masterchain_create_fee, &basechain_create_fee, wc, utime);
if(fetch_res.is_error()) {
auto error = fetch_res.move_as_error();
LOG(DEBUG) << "Cannot fetch config params: " << error.message();
@ -152,10 +151,9 @@ td::Status ExtMessageQ::run_message_on_account(ton::WorkchainId wc,
compute_phase_cfg_.with_vm_log = true;
compute_phase_cfg_.stop_on_accept_message = true;
auto res = Collator::impl_create_ordinary_transaction(msg_root, acc, utime, lt,
&storage_phase_cfg_, &compute_phase_cfg_,
&action_phase_cfg_,
true, lt);
auto res =
Collator::impl_create_ordinary_transaction(msg_root, acc, utime, lt, &storage_phase_cfg_, &compute_phase_cfg_,
&action_phase_cfg_, &serialize_config_, true, lt);
if(res.is_error()) {
auto error = res.move_as_error();
LOG(DEBUG) << "Cannot run message on account: " << error.message();

View file

@ -1004,6 +1004,10 @@ bool ValidateQuery::fetch_config_params() {
action_phase_cfg_.disable_custom_fess = config_->get_global_version() >= 8;
action_phase_cfg_.reserve_extra_enabled = config_->get_global_version() >= 9;
action_phase_cfg_.mc_blackhole_addr = config_->get_burning_config().blackhole_addr;
action_phase_cfg_.extra_currency_v2 = config_->get_global_version() >= 10;
}
{
serialize_cfg_.extra_currency_v2 = config_->get_global_version() >= 10;
}
{
// fetch block_grams_created
@ -5608,7 +5612,7 @@ bool ValidateQuery::check_one_transaction(block::Account& account, ton::LogicalT
return reject_query(PSTRING() << "cannot re-create bounce phase of transaction " << lt << " for smart contract "
<< addr.to_hex());
}
if (!trs->serialize()) {
if (!trs->serialize(serialize_cfg_)) {
return reject_query(PSTRING() << "cannot re-create the serialization of transaction " << lt
<< " for smart contract " << addr.to_hex());
}

View file

@ -205,6 +205,7 @@ class ValidateQuery : public td::actor::Actor {
block::StoragePhaseConfig storage_phase_cfg_{&storage_prices_};
block::ComputePhaseConfig compute_phase_cfg_;
block::ActionPhaseConfig action_phase_cfg_;
block::SerializeConfig serialize_cfg_;
td::RefInt256 masterchain_create_fee_, basechain_create_fee_;
std::vector<block::McShardDescr> neighbors_;