Skip to content

Commit a11ffb1

Browse files
Add DUEPAYMENT and some others + small fixes of new opcodes (ton-blockchain#881)
* Changes in TVM v6 * Rename some opcodes * Add due payment to c7 * Add GETORIGINALFWDFEE, GETGASFEESIMPLE, GETFORWARDFEESIMPLE * Bugfix in GETGASFEE * Fix typo --------- Co-authored-by: SpyCheese <[email protected]>
1 parent 51d30e2 commit a11ffb1

File tree

6 files changed

+99
-42
lines changed

6 files changed

+99
-42
lines changed

crypto/block/transaction.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -1339,7 +1339,8 @@ Ref<vm::Tuple> Transaction::prepare_vm_c7(const ComputePhaseConfig& cfg) const {
13391339
}
13401340
if (cfg.global_version >= 6) {
13411341
tuple.push_back(cfg.unpacked_config_tuple.not_null() ? vm::StackEntry(cfg.unpacked_config_tuple)
1342-
: vm::StackEntry()); // unpacked_config_tuple:[...]
1342+
: vm::StackEntry()); // unpacked_config_tuple:[...]
1343+
tuple.push_back(due_payment.not_null() ? due_payment : td::zero_refint()); // due_payment:Integer
13431344
}
13441345
auto tuple_ref = td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(tuple));
13451346
LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple_ref).to_string();
@@ -1938,9 +1939,9 @@ td::uint64 MsgPrices::compute_fwd_fees(td::uint64 cells, td::uint64 bits) const
19381939
* @returns The computed forward fees for the message as td::RefInt256j.
19391940
*/
19401941
td::RefInt256 MsgPrices::compute_fwd_fees256(td::uint64 cells, td::uint64 bits) const {
1941-
return td::rshift(
1942-
td::make_refint(lump_price) + td::make_refint(bit_price) * bits + td::make_refint(cell_price) * cells, 16,
1943-
1); // divide by 2^16 with ceil rounding
1942+
return td::make_refint(lump_price) +
1943+
td::rshift(td::make_refint(bit_price) * bits + td::make_refint(cell_price) * cells, 16,
1944+
1); // divide by 2^16 with ceil rounding
19441945
}
19451946

19461947
/**

crypto/fift/lib/Asm.fif

+7-3
Original file line numberDiff line numberDiff line change
@@ -1302,16 +1302,20 @@ x{F82B} @Defop INCOMINGVALUE
13021302
x{F82C} @Defop STORAGEFEES
13031303
x{F82D} @Defop PREVBLOCKSINFOTUPLE
13041304
x{F82E} @Defop UNPACKEDCONFIGTUPLE
1305+
x{F82F} @Defop DUEPAYMENT
13051306
x{F830} @Defop CONFIGDICT
13061307
x{F832} @Defop CONFIGPARAM
13071308
x{F833} @Defop CONFIGOPTPARAM
13081309
x{F83400} @Defop PREVMCBLOCKS
13091310
x{F83401} @Defop PREVKEYBLOCK
13101311
x{F835} @Defop GLOBALID
1311-
x{F836} @Defop GETEXECUTIONPRICE
1312-
x{F837} @Defop GETSTORAGEPRICE
1313-
x{F838} @Defop GETFORWARDPRICE
1312+
x{F836} @Defop GETGASFEE
1313+
x{F837} @Defop GETSTORAGEFEE
1314+
x{F838} @Defop GETFORWARDFEE
13141315
x{F839} @Defop GETPRECOMPILEDGAS
1316+
x{F83A} @Defop GETORIGINALFWDFEE
1317+
x{F83B} @Defop GETGASFEESIMPLE
1318+
x{F83C} @Defop GETFORWARDFEESIMPLE
13151319

13161320
x{F840} @Defop GETGLOBVAR
13171321
{ dup 1 31 @rangechk <b x{F85_} s, swap 5 u, @addopb } : GETGLOB

crypto/smc-envelope/SmartContract.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ td::Ref<vm::Tuple> prepare_vm_c7(SmartContract::Args args, td::Ref<vm::Cell> cod
173173
}
174174
if (args.config && args.config.value()->get_global_version() >= 6) {
175175
tuple.push_back(args.config.value()->get_unpacked_config_tuple(now)); // unpacked_config_tuple
176+
tuple.push_back(td::zero_refint()); // due_payment
176177
}
177178
auto tuple_ref = td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(tuple));
178179
//LOG(DEBUG) << "SmartContractInfo initialized with " << vm::StackEntry(tuple).to_string();

crypto/vm/tonops.cpp

+69-23
Original file line numberDiff line numberDiff line change
@@ -276,11 +276,7 @@ int exec_get_global_id(VmState* st) {
276276
return 0;
277277
}
278278

279-
int exec_get_execution_price(VmState* st) {
280-
VM_LOG(st) << "execute GETEXECUTIONPRICE";
281-
Stack& stack = st->get_stack();
282-
bool is_masterchain = stack.pop_bool();
283-
td::uint64 gas = stack.pop_long_range(std::numeric_limits<td::int64>::max(), 0);
279+
static block::GasLimitsPrices get_gas_prices(VmState* st, bool is_masterchain) {
284280
Ref<CellSlice> cs = get_unpacked_config_param(st, is_masterchain ? 2 : 3);
285281
if (cs.is_null()) {
286282
throw VmError{Excno::type_chk, "intermediate value is not a slice"};
@@ -289,13 +285,33 @@ int exec_get_execution_price(VmState* st) {
289285
if (r_prices.is_error()) {
290286
throw VmError{Excno::cell_und, PSTRING() << "cannot parse config: " << r_prices.error().message()};
291287
}
292-
block::GasLimitsPrices prices = r_prices.move_as_ok();
288+
return r_prices.move_as_ok();
289+
}
290+
291+
static block::MsgPrices get_msg_prices(VmState* st, bool is_masterchain) {
292+
Ref<CellSlice> cs = get_unpacked_config_param(st, is_masterchain ? 4 : 5);
293+
if (cs.is_null()) {
294+
throw VmError{Excno::type_chk, "intermediate value is not a slice"};
295+
}
296+
auto r_prices = block::Config::do_get_msg_prices(*cs, is_masterchain ? 24 : 25);
297+
if (r_prices.is_error()) {
298+
throw VmError{Excno::cell_und, PSTRING() << "cannot parse config: " << r_prices.error().message()};
299+
}
300+
return r_prices.move_as_ok();
301+
}
302+
303+
int exec_get_gas_fee(VmState* st) {
304+
VM_LOG(st) << "execute GETGASFEE";
305+
Stack& stack = st->get_stack();
306+
bool is_masterchain = stack.pop_bool();
307+
td::uint64 gas = stack.pop_long_range(std::numeric_limits<td::int64>::max(), 0);
308+
block::GasLimitsPrices prices = get_gas_prices(st, is_masterchain);
293309
stack.push_int(prices.compute_gas_price(gas));
294310
return 0;
295311
}
296312

297-
int exec_get_storage_price(VmState* st) {
298-
VM_LOG(st) << "execute GETSTORAGEPRICE";
313+
int exec_get_storage_fee(VmState* st) {
314+
VM_LOG(st) << "execute GETSTORAGEFEE";
299315
Stack& stack = st->get_stack();
300316
bool is_masterchain = stack.pop_bool();
301317
td::int64 delta = stack.pop_long_range(std::numeric_limits<td::int64>::max(), 0);
@@ -325,21 +341,13 @@ int exec_get_storage_price(VmState* st) {
325341
return 0;
326342
}
327343

328-
int exec_get_forward_price(VmState* st) {
329-
VM_LOG(st) << "execute GETFORWARDPRICE";
344+
int exec_get_forward_fee(VmState* st) {
345+
VM_LOG(st) << "execute GETFORWARDFEE";
330346
Stack& stack = st->get_stack();
331347
bool is_masterchain = stack.pop_bool();
332348
td::uint64 bits = stack.pop_long_range(std::numeric_limits<td::int64>::max(), 0);
333349
td::uint64 cells = stack.pop_long_range(std::numeric_limits<td::int64>::max(), 0);
334-
Ref<CellSlice> cs = get_unpacked_config_param(st, is_masterchain ? 4 : 5);
335-
if (cs.is_null()) {
336-
throw VmError{Excno::type_chk, "intermediate value is not a slice"};
337-
}
338-
auto r_prices = block::Config::do_get_msg_prices(*cs, is_masterchain ? 24 : 25);
339-
if (r_prices.is_error()) {
340-
throw VmError{Excno::cell_und, PSTRING() << "cannot parse config: " << r_prices.error().message()};
341-
}
342-
block::MsgPrices prices = r_prices.move_as_ok();
350+
block::MsgPrices prices = get_msg_prices(st, is_masterchain);
343351
stack.push_int(prices.compute_fwd_fees256(cells, bits));
344352
return 0;
345353
}
@@ -351,6 +359,41 @@ int exec_get_precompiled_gas(VmState* st) {
351359
return 0;
352360
}
353361

362+
int exec_get_original_fwd_fee(VmState* st) {
363+
VM_LOG(st) << "execute GETORIGINALFWDFEE";
364+
Stack& stack = st->get_stack();
365+
bool is_masterchain = stack.pop_bool();
366+
td::RefInt256 fwd_fee = stack.pop_int_finite();
367+
if (fwd_fee->sgn() < 0) {
368+
throw VmError{Excno::range_chk, "fwd_fee is negative"};
369+
}
370+
block::MsgPrices prices = get_msg_prices(st, is_masterchain);
371+
stack.push_int(td::muldiv(fwd_fee, td::make_refint(1 << 16), td::make_refint((1 << 16) - prices.first_frac)));
372+
return 0;
373+
}
374+
375+
int exec_get_gas_fee_simple(VmState* st) {
376+
VM_LOG(st) << "execute GETGASFEESIMPLE";
377+
Stack& stack = st->get_stack();
378+
bool is_masterchain = stack.pop_bool();
379+
td::uint64 gas = stack.pop_long_range(std::numeric_limits<td::int64>::max(), 0);
380+
block::GasLimitsPrices prices = get_gas_prices(st, is_masterchain);
381+
stack.push_int(td::rshift(td::make_refint(prices.gas_price) * gas, 16, 1));
382+
return 0;
383+
}
384+
385+
int exec_get_forward_fee_simple(VmState* st) {
386+
VM_LOG(st) << "execute GETFORWARDFEESIMPLE";
387+
Stack& stack = st->get_stack();
388+
bool is_masterchain = stack.pop_bool();
389+
td::uint64 bits = stack.pop_long_range(std::numeric_limits<td::int64>::max(), 0);
390+
td::uint64 cells = stack.pop_long_range(std::numeric_limits<td::int64>::max(), 0);
391+
block::MsgPrices prices = get_msg_prices(st, is_masterchain);
392+
stack.push_int(td::rshift(td::make_refint(prices.bit_price) * bits + td::make_refint(prices.cell_price) * cells, 16,
393+
1)); // divide by 2^16 with ceil rounding
394+
return 0;
395+
}
396+
354397
void register_ton_config_ops(OpcodeTable& cp0) {
355398
using namespace std::placeholders;
356399
cp0.insert(OpcodeInstr::mkfixedrange(0xf820, 0xf823, 16, 4, instr::dump_1c("GETPARAM "), exec_get_var_param))
@@ -366,17 +409,20 @@ void register_ton_config_ops(OpcodeTable& cp0) {
366409
.insert(OpcodeInstr::mksimple(0xf82c, 16, "STORAGEFEES", std::bind(exec_get_param, _1, 12, "STORAGEFEES")))
367410
.insert(OpcodeInstr::mksimple(0xf82d, 16, "PREVBLOCKSINFOTUPLE", std::bind(exec_get_param, _1, 13, "PREVBLOCKSINFOTUPLE")))
368411
.insert(OpcodeInstr::mksimple(0xf82e, 16, "UNPACKEDCONFIGTUPLE", std::bind(exec_get_param, _1, 14, "UNPACKEDCONFIGTUPLE")))
369-
.insert(OpcodeInstr::mkfixedrange(0xf82f, 0xf830, 16, 4, instr::dump_1c("GETPARAM "), exec_get_var_param))
412+
.insert(OpcodeInstr::mksimple(0xf82f, 16, "DUEPAYMENT", std::bind(exec_get_param, _1, 15, "DUEPAYMENT")))
370413
.insert(OpcodeInstr::mksimple(0xf830, 16, "CONFIGDICT", exec_get_config_dict))
371414
.insert(OpcodeInstr::mksimple(0xf832, 16, "CONFIGPARAM", std::bind(exec_get_config_param, _1, false)))
372415
.insert(OpcodeInstr::mksimple(0xf833, 16, "CONFIGOPTPARAM", std::bind(exec_get_config_param, _1, true)))
373416
.insert(OpcodeInstr::mksimple(0xf83400, 24, "PREVMCBLOCKS", std::bind(exec_get_prev_blocks_info, _1, 0, "PREVMCBLOCKS"))->require_version(4))
374417
.insert(OpcodeInstr::mksimple(0xf83401, 24, "PREVKEYBLOCK", std::bind(exec_get_prev_blocks_info, _1, 1, "PREVKEYBLOCK"))->require_version(4))
375418
.insert(OpcodeInstr::mksimple(0xf835, 16, "GLOBALID", exec_get_global_id)->require_version(4))
376-
.insert(OpcodeInstr::mksimple(0xf836, 16, "GETEXECUTIONPRICE", exec_get_execution_price)->require_version(6))
377-
.insert(OpcodeInstr::mksimple(0xf837, 16, "GETSTORAGEPRICE", exec_get_storage_price)->require_version(6))
378-
.insert(OpcodeInstr::mksimple(0xf838, 16, "GETFORWARDPRICE", exec_get_forward_price)->require_version(6))
419+
.insert(OpcodeInstr::mksimple(0xf836, 16, "GETGASFEE", exec_get_gas_fee)->require_version(6))
420+
.insert(OpcodeInstr::mksimple(0xf837, 16, "GETSTORAGEFEE", exec_get_storage_fee)->require_version(6))
421+
.insert(OpcodeInstr::mksimple(0xf838, 16, "GETFORWARDFEE", exec_get_forward_fee)->require_version(6))
379422
.insert(OpcodeInstr::mksimple(0xf839, 16, "GETPRECOMPILEDGAS", exec_get_precompiled_gas)->require_version(6))
423+
.insert(OpcodeInstr::mksimple(0xf83a, 16, "GETORIGINALFWDFEE", exec_get_original_fwd_fee)->require_version(6))
424+
.insert(OpcodeInstr::mksimple(0xf83b, 16, "GETGASFEESIMPLE", exec_get_gas_fee_simple)->require_version(6))
425+
.insert(OpcodeInstr::mksimple(0xf83c, 16, "GETFORWARDFEESIMPLE", exec_get_forward_fee_simple)->require_version(6))
380426
.insert(OpcodeInstr::mksimple(0xf840, 16, "GETGLOBVAR", exec_get_global_var))
381427
.insert(OpcodeInstr::mkfixedrange(0xf841, 0xf860, 16, 5, instr::dump_1c_and(31, "GETGLOB "), exec_get_global))
382428
.insert(OpcodeInstr::mksimple(0xf860, 16, "SETGLOBVAR", exec_set_global_var))

doc/GlobalVersions.md

+16-12
Original file line numberDiff line numberDiff line change
@@ -58,23 +58,27 @@ See [this post](https://t.me/tonstatus/88) for details.
5858
## Version 6
5959

6060
### c7 tuple
61-
**c7** tuple extended from 14 to 15 elements. The new element is a tuple that contains some config parameters as cell slices.
62-
If the parameter is absent from the config, the value is null.
63-
* **0**: `StoragePrices` from `ConfigParam 18`. Not the whole dict, but only the one StoragePrices entry (one which corresponds to the current time).
64-
* **1**: `ConfigParam 19` (global id).
65-
* **2**: `ConfigParam 20` (mc gas prices).
66-
* **3**: `ConfigParam 21` (gas prices).
67-
* **4**: `ConfigParam 24` (mc fwd fees).
68-
* **5**: `ConfigParam 25` (fwd fees).
69-
* **6**: `ConfigParam 43` (size limits).
61+
**c7** tuple extended from 14 to 16 elements:
62+
* **14**: tuple that contains some config parameters as cell slices. If the parameter is absent from the config, the value is null. Asm opcode: `UNPACKEDCONFIGTUPLE`.
63+
* **0**: `StoragePrices` from `ConfigParam 18`. Not the whole dict, but only the one StoragePrices entry (one which corresponds to the current time).
64+
* **1**: `ConfigParam 19` (global id).
65+
* **2**: `ConfigParam 20` (mc gas prices).
66+
* **3**: `ConfigParam 21` (gas prices).
67+
* **4**: `ConfigParam 24` (mc fwd fees).
68+
* **5**: `ConfigParam 25` (fwd fees).
69+
* **6**: `ConfigParam 43` (size limits).
70+
* **15**: "[due payment](https://github.com/ton-blockchain/ton/blob/8a9ff339927b22b72819c5125428b70c406da631/crypto/block/block.tlb#L237)" - current debt for storage fee (nanotons). Asm opcode: `DUEPAYMENT`.
7071

7172
### New TVM instructions
7273

7374
#### Fee calculation
74-
* `GETEXECUTIONPRICE` (`gas_used is_mc - price`) - calculates gas fee.
75-
* `GETSTORAGEPRICE` (`cells bits seconds is_mc - price`) - calculates storage fees (only current StoragePrices entry is used).
76-
* `GETFORWARDPRICE` (`cells bits is_mc - price`) - calculates forward fee.
75+
* `GETGASFEE` (`gas_used is_mc - price`) - calculates gas fee.
76+
* `GETSTORAGEFEE` (`cells bits seconds is_mc - price`) - calculates storage fees (only current StoragePrices entry is used).
77+
* `GETFORWARDFEE` (`cells bits is_mc - price`) - calculates forward fee.
7778
* `GETPRECOMPILEDGAS` (`- null`) - reserved, currently returns `null`.
79+
* `GETORIGINALFWDFEE` (`fwd_fee is_mc - orig_fwd_fee`) - calculate `fwd_fee * 2^16 / first_frac`. Can be used to get the original `fwd_fee` of the message.
80+
* `GETGASFEESIMPLE` (`gas_used is_mc - price`) - same as `GETGASFEE`, but without flat price (just `(gas_used * price) / 2^16`).
81+
* `GETFORWARDFEESIMPLE` (`cells bits is_mc - price`) - same as `GETFORWARDFEE`, but without lump price (just `(bits*bit_price + cells*cell_price) / 2^16`).
7882

7983
`gas_used`, `cells`, `bits`, `time_delta` are integers in range `0..2^63-1`.
8084

utils/opcode-timing.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ void prepare_c7() {
5757
} else {
5858
tuple.push_back(vm::StackEntry());
5959
}
60+
tuple.push_back(td::zero_refint());
6061
auto tuple_ref = td::make_cnt_ref<std::vector<vm::StackEntry>>(std::move(tuple));
6162
c7 = vm::make_tuple_ref(std::move(tuple_ref));
6263
}

0 commit comments

Comments
 (0)