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

updated tonlib, fixed bugs

updated tonlib
fixed bugs in func
validator: partial support for hardforks
liteserver: support for waitMasterchainBlock prefix
transactions: support for gas flat rate
This commit is contained in:
ton 2019-10-03 17:04:52 +04:00
parent 841d5ebac2
commit 7ea00ebfcf
89 changed files with 1922 additions and 608 deletions

View file

@ -1143,6 +1143,20 @@ bool TrStoragePhase::validate_skip(vm::CellSlice& cs, bool weak) const {
&& t_AccStatusChange.validate_skip(cs, weak); // status_change:AccStatusChange
}
bool TrStoragePhase::get_storage_fees(vm::CellSlice& cs, td::RefInt256& storage_fees) const {
return t_Grams.as_integer_skip_to(cs, storage_fees); // storage_fees_collected:Grams
}
bool TrStoragePhase::maybe_get_storage_fees(vm::CellSlice& cs, td::RefInt256& storage_fees) const {
auto z = cs.fetch_ulong(1);
if (!z) {
storage_fees = td::make_refint(0);
return true;
} else {
return z == 1 && get_storage_fees(cs, storage_fees);
}
}
const TrStoragePhase t_TrStoragePhase;
bool TrCreditPhase::skip(vm::CellSlice& cs) const {
@ -1322,13 +1336,14 @@ bool TransactionDescr::skip(vm::CellSlice& cs) const {
&& t_TrStoragePhase.skip(cs); // storage_ph:TrStoragePhase
case trans_tick_tock:
return cs.advance(4) // trans_tick_tock$001 is_tock:Bool
&& t_TrStoragePhase.skip(cs) // storage:TrStoragePhase
&& t_TrStoragePhase.skip(cs) // storage_ph:TrStoragePhase
&& t_TrComputePhase.skip(cs) // compute_ph:TrComputePhase
&& Maybe<RefTo<TrActionPhase>>{}.skip(cs) // action:(Maybe ^TrActionPhase)
&& cs.advance(2); // aborted:Bool destroyed:Bool
case trans_split_prepare:
return cs.advance(4) // trans_split_prepare$0100
&& t_SplitMergeInfo.skip(cs) // split_info:SplitMergeInfo
&& Maybe<TrStoragePhase>{}.skip(cs) // storage_ph:(Maybe TrStoragePhase)
&& t_TrComputePhase.skip(cs) // compute_ph:TrComputePhase
&& Maybe<RefTo<TrActionPhase>>{}.skip(cs) // action:(Maybe ^TrActionPhase)
&& cs.advance(2); // aborted:Bool destroyed:Bool
@ -1346,6 +1361,7 @@ bool TransactionDescr::skip(vm::CellSlice& cs) const {
return cs.advance(4) // trans_merge_install$0111
&& t_SplitMergeInfo.skip(cs) // split_info:SplitMergeInfo
&& t_Ref_Transaction.skip(cs) // prepare_transaction:^Transaction
&& Maybe<TrStoragePhase>{}.skip(cs) // storage_ph:(Maybe TrStoragePhase)
&& Maybe<TrCreditPhase>{}.skip(cs) // credit_ph:(Maybe TrCreditPhase)
&& Maybe<TrComputePhase>{}.skip(cs) // compute_ph:TrComputePhase
&& Maybe<RefTo<TrActionPhase>>{}.skip(cs) // action:(Maybe ^TrActionPhase)
@ -1370,13 +1386,14 @@ bool TransactionDescr::validate_skip(vm::CellSlice& cs, bool weak) const {
&& t_TrStoragePhase.validate_skip(cs, weak); // storage_ph:TrStoragePhase
case trans_tick_tock:
return cs.advance(4) // trans_tick_tock$001 is_tock:Bool
&& t_TrStoragePhase.validate_skip(cs, weak) // storage:TrStoragePhase
&& t_TrStoragePhase.validate_skip(cs, weak) // storage_ph:TrStoragePhase
&& t_TrComputePhase.validate_skip(cs, weak) // compute_ph:TrComputePhase
&& Maybe<RefTo<TrActionPhase>>{}.validate_skip(cs, weak) // action:(Maybe ^TrActionPhase)
&& cs.advance(2); // aborted:Bool destroyed:Bool
case trans_split_prepare:
return cs.advance(4) // trans_split_prepare$0100
&& t_SplitMergeInfo.validate_skip(cs, weak) // split_info:SplitMergeInfo
&& Maybe<TrStoragePhase>{}.validate_skip(cs, weak) // storage_ph:(Maybe TrStoragePhase)
&& t_TrComputePhase.validate_skip(cs, weak) // compute_ph:TrComputePhase
&& Maybe<RefTo<TrActionPhase>>{}.validate_skip(cs, weak) // action:(Maybe ^TrActionPhase)
&& cs.advance(2); // aborted:Bool destroyed:Bool
@ -1394,6 +1411,7 @@ bool TransactionDescr::validate_skip(vm::CellSlice& cs, bool weak) const {
return cs.advance(4) // trans_merge_install$0111
&& t_SplitMergeInfo.validate_skip(cs, weak) // split_info:SplitMergeInfo
&& t_Ref_Transaction.validate_skip(cs, weak) // prepare_transaction:^Transaction
&& Maybe<TrStoragePhase>{}.validate_skip(cs, weak) // storage_ph:(Maybe TrStoragePhase)
&& Maybe<TrCreditPhase>{}.validate_skip(cs, weak) // credit_ph:(Maybe TrCreditPhase)
&& Maybe<TrComputePhase>{}.validate_skip(cs, weak) // compute_ph:TrComputePhase
&& Maybe<RefTo<TrActionPhase>>{}.validate_skip(cs, weak) // action:(Maybe ^TrActionPhase)
@ -1407,6 +1425,53 @@ int TransactionDescr::get_tag(const vm::CellSlice& cs) const {
return (t >= 0 && t <= 7) ? (t == 3 ? 2 : t) : -1;
}
bool TransactionDescr::skip_to_storage_phase(vm::CellSlice& cs, bool& found) const {
found = false;
switch (get_tag(cs)) {
case trans_ord:
return cs.advance(4 + 1) // trans_ord$0000 storage_first:Bool
&& cs.fetch_bool_to(found); // storage_ph:(Maybe TrStoragePhase)
case trans_storage:
return cs.advance(4) // trans_storage$0001
&& (found = true); // storage_ph:TrStoragePhase
case trans_tick_tock:
return cs.advance(4) // trans_tick_tock$001 is_tock:Bool
&& (found = true); // storage_ph:TrStoragePhase
case trans_split_prepare:
return cs.advance(4) // trans_split_prepare$0100
&& t_SplitMergeInfo.skip(cs) // split_info:SplitMergeInfo
&& cs.fetch_bool_to(found); // storage_ph:(Maybe TrStoragePhase)
case trans_split_install:
return true;
case trans_merge_prepare:
return cs.advance(4) // trans_merge_prepare$0110
&& t_SplitMergeInfo.skip(cs) // split_info:SplitMergeInfo
&& (found = true); // storage_ph:TrStoragePhase
case trans_merge_install:
return cs.advance(4) // trans_merge_install$0111
&& t_SplitMergeInfo.skip(cs) // split_info:SplitMergeInfo
&& t_Ref_Transaction.skip(cs) // prepare_transaction:^Transaction
&& cs.fetch_bool_to(found); // storage_ph:(Maybe TrStoragePhase)
}
return false;
}
bool TransactionDescr::get_storage_fees(Ref<vm::Cell> cell, td::RefInt256& storage_fees) const {
if (cell.is_null()) {
return false;
}
auto cs = vm::load_cell_slice(std::move(cell));
bool found;
if (!skip_to_storage_phase(cs, found)) {
return false;
} else if (found) {
return t_TrStoragePhase.get_storage_fees(cs, storage_fees);
} else {
storage_fees = td::make_refint(0);
return true;
}
}
const TransactionDescr t_TransactionDescr;
bool Transaction_aux::skip(vm::CellSlice& cs) const {
@ -1447,6 +1512,32 @@ bool Transaction::validate_skip(vm::CellSlice& cs, bool weak) const {
&& RefTo<TransactionDescr>{}.validate_skip(cs, weak); // description:^TransactionDescr
}
bool Transaction::get_storage_fees(Ref<vm::Cell> cell, td::RefInt256& storage_fees) const {
Ref<vm::Cell> tdescr;
return get_descr(std::move(cell), tdescr) && t_TransactionDescr.get_storage_fees(std::move(tdescr), storage_fees);
}
bool Transaction::get_descr(Ref<vm::Cell> cell, Ref<vm::Cell>& tdescr) const {
if (cell.is_null()) {
return false;
} else {
auto cs = vm::load_cell_slice(std::move(cell));
return cs.is_valid() && get_descr(cs, tdescr) && cs.empty_ext();
}
}
bool Transaction::get_descr(vm::CellSlice& cs, Ref<vm::Cell>& tdescr) const {
return cs.advance(
4 + 256 + 64 + 256 + 64 + 32 +
15) // transaction$0111 account_addr:uint256 lt:uint64 prev_trans_hash:bits256 prev_trans_lt:uint64 now:uint32 outmsg_cnt:uint15
&& t_AccountStatus.skip(cs) // orig_status:AccountStatus
&& t_AccountStatus.skip(cs) // end_status:AccountStatus
&& cs.advance_refs(1) // ^[ in_msg:(Maybe ^Message) out_msgs:(HashmapE 15 ^Message) ]
&& t_CurrencyCollection.skip(cs) // total_fees:CurrencyCollection
&& cs.advance_refs(1) // state_update:^(MERKLE_UPDATE Account)
&& cs.fetch_ref_to(tdescr); // description:^TransactionDescr
}
bool Transaction::get_total_fees(vm::CellSlice&& cs, block::CurrencyCollection& total_fees) const {
return cs.is_valid() && cs.fetch_ulong(4) == 7 // transaction$0111
&&

View file

@ -614,6 +614,8 @@ extern const AccStatusChange t_AccStatusChange;
struct TrStoragePhase final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool get_storage_fees(vm::CellSlice& cs, td::RefInt256& storage_fees) const;
bool maybe_get_storage_fees(vm::CellSlice& cs, td::RefInt256& storage_fees) const;
};
extern const TrStoragePhase t_TrStoragePhase;
@ -693,6 +695,8 @@ struct TransactionDescr final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
int get_tag(const vm::CellSlice& cs) const override;
bool skip_to_storage_phase(vm::CellSlice& cs, bool& found) const;
bool get_storage_fees(Ref<vm::Cell> cell, td::RefInt256& storage_fees) const;
};
extern const TransactionDescr t_TransactionDescr;
@ -708,6 +712,9 @@ struct Transaction final : TLB_Complex {
bool skip(vm::CellSlice& cs) const override;
bool validate_skip(vm::CellSlice& cs, bool weak = false) const override;
bool get_total_fees(vm::CellSlice&& cs, block::CurrencyCollection& total_fees) const;
bool get_descr(Ref<vm::Cell> cell, Ref<vm::Cell>& tdescr) const;
bool get_descr(vm::CellSlice& cs, Ref<vm::Cell>& tdescr) const;
bool get_storage_fees(Ref<vm::Cell> cell, td::RefInt256& storage_fees) const;
};
extern const Transaction t_Transaction;

View file

@ -325,7 +325,7 @@ trans_ord$0000 credit_first:Bool
trans_storage$0001 storage_ph:TrStoragePhase
= TransactionDescr;
trans_tick_tock$001 is_tock:Bool storage:TrStoragePhase
trans_tick_tock$001 is_tock:Bool storage_ph:TrStoragePhase
compute_ph:TrComputePhase action:(Maybe ^TrActionPhase)
aborted:Bool destroyed:Bool = TransactionDescr;
//
@ -333,6 +333,7 @@ split_merge_info$_ cur_shard_pfx_len:(## 6)
acc_split_depth:(## 6) this_addr:bits256 sibling_addr:bits256
= SplitMergeInfo;
trans_split_prepare$0100 split_info:SplitMergeInfo
storage_ph:(Maybe TrStoragePhase)
compute_ph:TrComputePhase action:(Maybe ^TrActionPhase)
aborted:Bool destroyed:Bool
= TransactionDescr;
@ -345,6 +346,7 @@ trans_merge_prepare$0110 split_info:SplitMergeInfo
= TransactionDescr;
trans_merge_install$0111 split_info:SplitMergeInfo
prepare_transaction:^Transaction
storage_ph:(Maybe TrStoragePhase)
credit_ph:(Maybe TrCreditPhase)
compute_ph:TrComputePhase action:(Maybe ^TrActionPhase)
aborted:Bool destroyed:Bool
@ -609,6 +611,9 @@ gas_prices_ext#de gas_price:uint64 gas_limit:uint64 special_gas_limit:uint64 gas
block_gas_limit:uint64 freeze_due_limit:uint64 delete_due_limit:uint64
= GasLimitsPrices;
gas_flat_pfx#d1 flat_gas_limit:uint64 flat_gas_price:uint64 other:GasLimitsPrices
= GasLimitsPrices;
config_mc_gas_prices#_ GasLimitsPrices = ConfigParam 20;
config_gas_prices#_ GasLimitsPrices = ConfigParam 21;

View file

@ -672,9 +672,56 @@ bool Transaction::prepare_credit_phase() {
return true;
}
bool ComputePhaseConfig::parse_GasLimitsPrices(Ref<vm::Cell> cell, td::RefInt256& freeze_due_limit,
td::RefInt256& delete_due_limit) {
return cell.not_null() &&
parse_GasLimitsPrices(vm::load_cell_slice_ref(std::move(cell)), freeze_due_limit, delete_due_limit);
}
bool ComputePhaseConfig::parse_GasLimitsPrices(Ref<vm::CellSlice> cs, td::RefInt256& freeze_due_limit,
td::RefInt256& delete_due_limit) {
if (cs.is_null()) {
return false;
}
block::gen::GasLimitsPrices::Record_gas_flat_pfx flat;
if (tlb::csr_unpack(cs, flat)) {
bool ok = parse_GasLimitsPrices(std::move(flat.other), freeze_due_limit, delete_due_limit);
flat_gas_limit = flat.flat_gas_limit;
flat_gas_price = flat.flat_gas_price;
return ok;
}
flat_gas_limit = flat_gas_price = 0;
auto f = [&](const auto& r, td::uint64 spec_limit) {
gas_limit = r.gas_limit;
special_gas_limit = spec_limit;
gas_credit = r.gas_credit;
gas_price = r.gas_price;
freeze_due_limit = td::RefInt256{true, r.freeze_due_limit};
delete_due_limit = td::RefInt256{true, r.delete_due_limit};
};
block::gen::GasLimitsPrices::Record_gas_prices_ext rec;
if (tlb::csr_unpack(cs, rec)) {
f(rec, rec.special_gas_limit);
} else {
block::gen::GasLimitsPrices::Record_gas_prices rec0;
if (tlb::csr_unpack(std::move(cs), rec0)) {
f(rec0, rec0.gas_limit);
} else {
return false;
}
}
compute_threshold();
return true;
}
void ComputePhaseConfig::compute_threshold() {
gas_price256 = td::RefInt256{true, gas_price};
max_gas_threshold = td::rshift(gas_price256 * gas_limit, 16, 1);
if (gas_limit > flat_gas_limit) {
max_gas_threshold =
td::rshift(gas_price256 * (gas_limit - flat_gas_limit), 16, 1) + td::make_refint(flat_gas_price);
} else {
max_gas_threshold = td::make_refint(flat_gas_price);
}
}
td::uint64 ComputePhaseConfig::gas_bought_for(td::RefInt256 nanograms) const {
@ -684,8 +731,11 @@ td::uint64 ComputePhaseConfig::gas_bought_for(td::RefInt256 nanograms) const {
if (nanograms >= max_gas_threshold) {
return gas_limit;
}
auto res = td::div(std::move(nanograms) << 16, gas_price256);
return res->to_long();
if (nanograms < flat_gas_price) {
return 0;
}
auto res = td::div((std::move(nanograms) - flat_gas_price) << 16, gas_price256);
return res->to_long() + flat_gas_limit;
}
td::RefInt256 ComputePhaseConfig::compute_gas_price(td::uint64 gas_used) const {
@ -855,6 +905,16 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) {
cp.skip_reason = ComputePhase::sk_no_gas;
return true;
}
// Compute gas limits
if (!compute_gas_limits(cp, cfg)) {
compute_phase.reset();
return false;
}
if (!cp.gas_limit && !cp.gas_credit) {
// no gas
cp.skip_reason = ComputePhase::sk_no_gas;
return true;
}
if (in_msg_state.not_null()) {
LOG(DEBUG) << "HASH(in_msg_state) = " << in_msg_state->get_hash().bits().to_hex(256)
<< ", account_state_hash = " << account.state_hash.to_hex();
@ -883,11 +943,6 @@ bool Transaction::prepare_compute_phase(const ComputePhaseConfig& cfg) {
} else if (in_msg_state.not_null()) {
unpack_msg_state(true); // use only libraries
}
// Compute gas limits
if (!compute_gas_limits(cp, cfg)) {
compute_phase.reset();
return false;
}
// initialize VM
Ref<vm::Stack> stack = prepare_vm_stack(cp);
if (stack.is_null()) {

View file

@ -98,6 +98,8 @@ struct ComputePhaseConfig {
td::uint64 gas_limit;
td::uint64 special_gas_limit;
td::uint64 gas_credit;
td::uint64 flat_gas_limit = 0;
td::uint64 flat_gas_price = 0;
static constexpr td::uint64 gas_infty = (1ULL << 63) - 1;
td::RefInt256 gas_price256;
td::RefInt256 max_gas_threshold;
@ -126,6 +128,8 @@ struct ComputePhaseConfig {
Ref<vm::Cell> get_lib_root() const {
return libraries ? libraries->get_root_cell() : Ref<vm::Cell>{};
}
bool parse_GasLimitsPrices(Ref<vm::CellSlice> cs, td::RefInt256& freeze_due_limit, td::RefInt256& delete_due_limit);
bool parse_GasLimitsPrices(Ref<vm::Cell> cell, td::RefInt256& freeze_due_limit, td::RefInt256& delete_due_limit);
};
// msg_fwd_fees = (lump_price + ceil((bit_price * msg.bits + cell_price * msg.cells)/2^16)) nanograms

View file

@ -764,6 +764,10 @@ void interpret_string_to_bytes(vm::Stack& stack) {
stack.push_bytes(stack.pop_string());
}
void interpret_bytes_to_string(vm::Stack& stack) {
stack.push_string(stack.pop_bytes());
}
void interpret_bytes_hash(vm::Stack& stack, bool as_uint) {
std::string str = stack.pop_bytes();
unsigned char buffer[32];
@ -796,7 +800,9 @@ void interpret_store_str(vm::Stack& stack) {
stack.check_underflow(2);
auto str = stack.pop_string();
auto cell = stack.pop_builder();
cell.write().store_bytes(str); // may throw CellWriteError
if (!cell.write().store_bytes_bool(str)) {
throw IntError{"string does not fit into cell"};
}
stack.push(cell);
}
@ -804,14 +810,18 @@ void interpret_store_bytes(vm::Stack& stack) {
stack.check_underflow(2);
auto str = stack.pop_bytes();
auto cell = stack.pop_builder();
cell.write().store_bytes(str); // may throw CellWriteError
if (!cell.write().store_bytes_bool(str)) {
throw IntError{"byte string does not fit into cell"};
}
stack.push(cell);
}
void interpret_string_to_cellslice(vm::Stack& stack) {
auto str = stack.pop_string();
vm::CellBuilder cb;
cb.store_bytes(str); // may throw CellWriteError
if (!cb.store_bytes_bool(str)) {
throw IntError{"string does not fit into cell"};
}
stack.push_cellslice(td::Ref<vm::CellSlice>{true, cb.finalize()});
}
@ -819,7 +829,9 @@ void interpret_store_cellslice(vm::Stack& stack) {
stack.check_underflow(2);
auto cs = stack.pop_cellslice();
auto cb = stack.pop_builder();
vm::cell_builder_add_slice(cb.write(), *cs);
if (!vm::cell_builder_add_slice_bool(cb.write(), *cs)) {
throw IntError{"slice does not fit into cell"};
}
stack.push(std::move(cb));
}
@ -840,9 +852,11 @@ void interpret_concat_cellslice(vm::Stack& stack) {
auto cs2 = stack.pop_cellslice();
auto cs1 = stack.pop_cellslice();
vm::CellBuilder cb;
vm::cell_builder_add_slice(cb, *cs1);
vm::cell_builder_add_slice(cb, *cs2);
stack.push_cellslice(td::Ref<vm::CellSlice>{true, cb.finalize()});
if (vm::cell_builder_add_slice_bool(cb, *cs1) && vm::cell_builder_add_slice_bool(cb, *cs2)) {
stack.push_cellslice(td::Ref<vm::CellSlice>{true, cb.finalize()});
} else {
throw IntError{"concatenation of two slices does not fit into a cell"};
}
}
void interpret_concat_cellslice_ref(vm::Stack& stack) {
@ -862,7 +876,9 @@ void interpret_concat_builders(vm::Stack& stack) {
stack.check_underflow(2);
auto cb2 = stack.pop_builder();
auto cb1 = stack.pop_builder();
cb1.write().append_builder(std::move(cb2));
if (!cb1.write().append_builder_bool(std::move(cb2))) {
throw IntError{"cannot concatenate two builders"};
}
stack.push_builder(std::move(cb1));
}
@ -2490,6 +2506,7 @@ void init_words_common(Dictionary& d) {
d.def_stack_word("B>Lu@+ ", std::bind(interpret_bytes_fetch_int, _1, 0x12));
d.def_stack_word("B>Li@+ ", std::bind(interpret_bytes_fetch_int, _1, 0x13));
d.def_stack_word("$>B ", interpret_string_to_bytes);
d.def_stack_word("B>$ ", interpret_bytes_to_string);
d.def_stack_word("Bhash ", std::bind(interpret_bytes_hash, _1, true));
d.def_stack_word("Bhashu ", std::bind(interpret_bytes_hash, _1, true));
d.def_stack_word("BhashB ", std::bind(interpret_bytes_hash, _1, false));

View file

@ -149,6 +149,10 @@ AsmOp AsmOp::IntConst(td::RefInt256 x) {
return AsmOp::Const(dec_string(std::move(x)) + " PUSHINT");
}
AsmOp AsmOp::BoolConst(bool f) {
return AsmOp::Const(f ? "TRUE" : "FALSE");
}
AsmOp AsmOp::Parse(std::string custom_op) {
if (custom_op == "NOP") {
return AsmOp::Nop();

View file

@ -620,7 +620,7 @@ int compute_compare(td::RefInt256 x, td::RefInt256 y, int mode) {
if (mode == 7) {
return s;
} else {
return (mode >> (1 - s)) & 1;
return -((mode >> (1 - s)) & 1);
}
}
@ -641,8 +641,8 @@ int compute_compare(const VarDescr& x, const VarDescr& y, int mode) {
return x.always_less(y) ? 1 : (x.always_geq(y) ? 2 : 3);
case 5: // <>
return x.always_neq(y) ? 1 : (x.always_equal(y) ? 2 : 3);
case 6: // >=
return x.always_geq(y) ? 1 : (x.always_less(y) ? 2 : 3);
case 6: // <=
return x.always_leq(y) ? 1 : (x.always_greater(y) ? 2 : 3);
case 7: // <=>
return x.always_less(y)
? 1
@ -661,10 +661,11 @@ AsmOp compile_cmp_int(std::vector<VarDescr>& res, std::vector<VarDescr>& args, i
assert(res.size() == 1 && args.size() == 2);
VarDescr &r = res[0], &x = args[0], &y = args[1];
if (x.is_int_const() && y.is_int_const()) {
r.set_const(compute_compare(x.int_const, y.int_const, mode));
int v = compute_compare(x.int_const, y.int_const, mode);
r.set_const(v);
x.unused();
y.unused();
return push_const(r.int_const);
return mode == 7 ? push_const(r.int_const) : AsmOp::BoolConst(v != 0);
}
int v = compute_compare(x, y, mode);
assert(v);
@ -672,7 +673,7 @@ AsmOp compile_cmp_int(std::vector<VarDescr>& res, std::vector<VarDescr>& args, i
r.set_const(v - (v >> 2) - 2);
x.unused();
y.unused();
return push_const(r.int_const);
return mode == 7 ? push_const(r.int_const) : AsmOp::BoolConst(v & 1);
}
r.val = ~0;
if (v & 1) {
@ -957,12 +958,11 @@ void define_builtins() {
AsmOp::Nop());
define_builtin_func("~dump", TypeExpr::new_forall({X}, TypeExpr::new_map(X, TypeExpr::new_tensor({X, Unit}))),
AsmOp::Custom("s0 DUMP", 1, 1));
define_builtin_func(
"run_method0", TypeExpr::new_map(Int, Unit),
[](auto a, auto b, auto c) { return compile_run_method(a, b, c, 0, false); }, true);
define_builtin_func_x(
"run_method1", TypeExpr::new_forall({X}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X}), Unit)),
[](auto a, auto b, auto c) { return compile_run_method(a, b, c, 1, false); }, {1, 0}, {}, true);
define_builtin_func("run_method0", TypeExpr::new_map(Int, Unit),
[](auto a, auto b, auto c) { return compile_run_method(a, b, c, 0, false); }, true);
define_builtin_func_x("run_method1",
TypeExpr::new_forall({X}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X}), Unit)),
[](auto a, auto b, auto c) { return compile_run_method(a, b, c, 1, false); }, {1, 0}, {}, true);
define_builtin_func_x(
"run_method2", TypeExpr::new_forall({X, Y}, TypeExpr::new_map(TypeExpr::new_tensor({Int, X, Y}), Unit)),
[](auto a, auto b, auto c) { return compile_run_method(a, b, c, 2, false); }, {1, 2, 0}, {}, true);

View file

@ -950,6 +950,7 @@ struct AsmOp {
static AsmOp make_stk2(int a, int b, const char* str, int delta);
static AsmOp make_stk3(int a, int b, int c, const char* str, int delta);
static AsmOp IntConst(td::RefInt256 value);
static AsmOp BoolConst(bool f);
static AsmOp Const(std::string push_op) {
return AsmOp(a_const, 0, 1, std::move(push_op));
}

View file

@ -101,8 +101,12 @@ dictnew constant special-dict
1 'nop
} ::_ sg~
// gas_price gas_limit spec_limit gas_credit block_gas_limit freeze_due_limit delete_due_limit -- c
{ 7 0 reverse <b x{de} s, { swap 64 u, } 7 times b>
// gas_price gas_limit spec_limit gas_credit block_gas_limit freeze_due_limit delete_due_limit b -- c
{ 7 1 reverse x{de} s, { swap 64 u, } 7 times b>
} : make-gas-prices-basic
// gas_price ... delete_due_limit flat_gas_limit flat_gas_rate -- c
{ 2dup or { <b x{d1} s, rot 64 u, swap 64 u, } { 2drop <b } cond
make-gas-prices-basic
} : make-gas-prices
{ make-gas-prices 20 config! } : config.mc_gas_prices!
{ make-gas-prices 21 config! } : config.gas_prices!

View file

@ -171,9 +171,9 @@ elector_addr config.elector_smc!
1 500 1000 500000 config.storage_prices!
config.special!
// gas_price gas_limit special_gas_limit gas_credit block_gas_limit freeze_due_limit delete_due_limit --
1000 sg* 1 *M dup 10000 10 *M GR$0.1 GR$1.0 config.gas_prices!
10000 sg* 1 *M 10 *M 10000 10 *M GR$0.1 GR$1.0 config.mc_gas_prices!
// gas_price gas_limit special_gas_limit gas_credit block_gas_limit freeze_due_limit delete_due_limit flat_gas_limit flat_gas_price --
1000 sg* 1 *M dup 10000 10 *M GR$0.1 GR$1.0 100 100000 config.gas_prices!
10000 sg* 1 *M 10 *M 10000 10 *M GR$0.1 GR$1.0 0 0 config.mc_gas_prices!
// lump_price bit_price cell_price ihr_factor first_frac next_frac
1000000 1000 sg* 100000 sg* 3/2 sg*/ 1/3 sg*/ 1/3 sg*/ config.fwd_prices!
10000000 10000 sg* 1000000 sg* 3/2 sg*/ 1/3 sg*/ 1/3 sg*/ config.mc_fwd_prices!

View file

@ -745,6 +745,26 @@ Ref<Cell> CellSlice::fetch_ref() {
}
}
bool CellSlice::prefetch_maybe_ref(Ref<vm::Cell>& res) const {
auto z = prefetch_ulong(1);
if (!z) {
res.clear();
return true;
} else {
return z == 1 && prefetch_ref_to(res);
}
}
bool CellSlice::fetch_maybe_ref(Ref<vm::Cell>& res) {
auto z = prefetch_ulong(1);
if (!z) {
res.clear();
return advance(1);
} else {
return z == 1 && prefetch_ref_to(res) && advance_ext(1, 1);
}
}
bool CellSlice::begins_with(unsigned bits, unsigned long long value) const {
return have(bits) && !((prefetch_ulong(bits) ^ value) & ((1ULL << bits) - 1));
}

View file

@ -185,6 +185,8 @@ class CellSlice : public td::CntObject {
bool prefetch_ref_to(Ref<Cell>& ref, unsigned offset = 0) const {
return (ref = prefetch_ref(offset)).not_null();
}
bool fetch_maybe_ref(Ref<Cell>& ref);
bool prefetch_maybe_ref(Ref<Cell>& ref) const;
td::BitSlice fetch_bits(unsigned bits);
td::BitSlice prefetch_bits(unsigned bits) const;
td::Ref<CellSlice> fetch_subslice(unsigned bits, unsigned refs = 0);