Skip to content

Commit

Permalink
Add TVM instructions for working with nonzero-level cells (ton-blockc…
Browse files Browse the repository at this point in the history
…hain#880)

Co-authored-by: SpyCheese <[email protected]>
  • Loading branch information
EmelyanenkoK and SpyCheese authored Jan 26, 2024
1 parent 64b04e4 commit 51d30e2
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 1 deletion.
6 changes: 6 additions & 0 deletions crypto/fift/lib/Asm.fif
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,12 @@ x{D761} @Defop LDONES
x{D762} @Defop LDSAME
x{D764} @Defop SDEPTH
x{D765} @Defop CDEPTH
x{D766} @Defop CLEVEL
x{D767} @Defop CLEVELMASK
{ <b x{D76A_} s, swap 2 u, @addopb } : CHASHI
{ <b x{D76E_} s, swap 2 u, @addopb } : CDEPTHI
x{D770} @Defop CHASHIX
x{D771} @Defop CDEPTHIX
//
// continuation / flow control primitives
x{D8} dup @Defop EXECUTE @Defop CALLX
Expand Down
4 changes: 4 additions & 0 deletions crypto/test/fift.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,7 @@ TEST(Fift, test_bls) {
TEST(Fift, test_bls_ops) {
run_fift("bls_ops.fif");
}

TEST(Fift, test_levels) {
run_fift("levels.fif");
}
75 changes: 75 additions & 0 deletions crypto/test/fift/levels.fif
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"Asm.fif" include
"FiftExt.fif" include

{
dup
."Cell " .dump cr
dup [[ <{ CLEVEL }>s ]] 0 runvmx abort"exitcode != 0" ."Level = " . cr
dup [[ <{ CLEVELMASK }>s ]] 0 runvmx abort"exitcode != 0" ."Level mask = 0b" b. cr
dup dup [[ <{ 0 CHASHI DUP ROT 0 INT CHASHIX EQUAL 55 THROWIFNOT }>s ]] 0 runvmx abort"exitcode != 0" ."Hash_0 = " X. cr
dup dup [[ <{ 1 CHASHI DUP ROT 1 INT CHASHIX EQUAL 55 THROWIFNOT }>s ]] 0 runvmx abort"exitcode != 0" ."Hash_1 = " X. cr
dup dup [[ <{ 2 CHASHI DUP ROT 2 INT CHASHIX EQUAL 55 THROWIFNOT }>s ]] 0 runvmx abort"exitcode != 0" ."Hash_2 = " X. cr
dup dup [[ <{ 3 CHASHI DUP ROT 3 INT CHASHIX EQUAL 55 THROWIFNOT }>s ]] 0 runvmx abort"exitcode != 0" ."Hash_3 = " X. cr
dup dup [[ <{ 0 CDEPTHI DUP ROT 0 INT CDEPTHIX EQUAL 55 THROWIFNOT }>s ]] 0 runvmx abort"exitcode != 0" ."Depth_0 = " . cr
dup dup [[ <{ 1 CDEPTHI DUP ROT 1 INT CDEPTHIX EQUAL 55 THROWIFNOT }>s ]] 0 runvmx abort"exitcode != 0" ."Depth_1 = " . cr
dup dup [[ <{ 2 CDEPTHI DUP ROT 2 INT CDEPTHIX EQUAL 55 THROWIFNOT }>s ]] 0 runvmx abort"exitcode != 0" ."Depth_2 = " . cr
dup dup [[ <{ 3 CDEPTHI DUP ROT 3 INT CDEPTHIX EQUAL 55 THROWIFNOT }>s ]] 0 runvmx abort"exitcode != 0" ."Depth_3 = " . cr
drop
cr
} : print-all

// Ordinary cell of level 0
<b
123 32 u,
<b <b 22 32 u, b> ref, b> ref,
<b b> ref,
b>
print-all

// Prunned branch of level 1
<b
1 8 u,
1 8 u,
0xabcd1111abcd1111abcd1111abcd1111abcd1111abcd1111abcd1111abcd1111 256 u,
14 16 u,
b>spec
print-all

// Prunned branch of level 3
<b
1 8 u,
7 8 u,
0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 256 u,
0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 256 u,
0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc 256 u,
55 16 u,
44 16 u,
33 16 u,
b>spec
print-all

// Prunned branch of level 3, mask 0b101
<b
1 8 u,
5 8 u,
0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 256 u,
0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc 256 u,
55 16 u,
33 16 u,
b>spec
print-all

// Tree with the previous cell inside
<b
<b
<b
1 8 u,
5 8 u,
0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 256 u,
0xcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc 256 u,
55 16 u,
33 16 u,
b>spec ref,
b> ref,
b>
print-all
57 changes: 56 additions & 1 deletion crypto/vm/cellops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1391,6 +1391,55 @@ int exec_slice_depth(VmState* st) {
return 0;
}

int exec_cell_level(VmState* st) {
Stack& stack = st->get_stack();
VM_LOG(st) << "execute CLEVEL";
auto cell = stack.pop_cell();
stack.push_smallint(cell->get_level());
return 0;
}

int exec_cell_level_mask(VmState* st) {
Stack& stack = st->get_stack();
VM_LOG(st) << "execute CLEVELMASK";
auto cell = stack.pop_cell();
stack.push_smallint(cell->get_level_mask().get_mask());
return 0;
}

int exec_cell_hash_i(VmState* st, unsigned args, bool var) {
unsigned i;
Stack& stack = st->get_stack();
if (var) {
VM_LOG(st) << "execute CHASHIX";
i = stack.pop_smallint_range(3);
} else {
i = args & 3;
VM_LOG(st) << "execute CHASHI " << i;
}
auto cell = stack.pop_cell();
std::array<unsigned char, 32> hash = cell->get_hash(i).as_array();
td::RefInt256 res{true};
CHECK(res.write().import_bytes(hash.data(), hash.size(), false));
stack.push_int(std::move(res));
return 0;
}

int exec_cell_depth_i(VmState* st, unsigned args, bool var) {
unsigned i;
Stack& stack = st->get_stack();
if (var) {
VM_LOG(st) << "execute CDEPTHIX";
i = stack.pop_smallint_range(3);
} else {
i = args & 3;
VM_LOG(st) << "execute CDEPTHI " << i;
}
auto cell = stack.pop_cell();
stack.push_smallint(cell->get_depth(i));
return 0;
}

void register_cell_deserialize_ops(OpcodeTable& cp0) {
using namespace std::placeholders;
cp0.insert(OpcodeInstr::mksimple(0xd0, 8, "CTOS", exec_cell_to_slice))
Expand Down Expand Up @@ -1479,7 +1528,13 @@ void register_cell_deserialize_ops(OpcodeTable& cp0) {
.insert(OpcodeInstr::mksimple(0xd761, 16, "LDONES", std::bind(exec_load_same, _1, "LDONES", 1)))
.insert(OpcodeInstr::mksimple(0xd762, 16, "LDSAME", std::bind(exec_load_same, _1, "LDSAME", -1)))
.insert(OpcodeInstr::mksimple(0xd764, 16, "SDEPTH", exec_slice_depth))
.insert(OpcodeInstr::mksimple(0xd765, 16, "CDEPTH", exec_cell_depth));
.insert(OpcodeInstr::mksimple(0xd765, 16, "CDEPTH", exec_cell_depth))
.insert(OpcodeInstr::mksimple(0xd766, 16, "CLEVEL", exec_cell_level)->require_version(6))
.insert(OpcodeInstr::mksimple(0xd767, 16, "CLEVELMASK", exec_cell_level_mask)->require_version(6))
.insert(OpcodeInstr::mkfixed(0xd768 >> 2, 14, 2, instr::dump_1c_and(3, "CHASHI "), std::bind(exec_cell_hash_i, _1, _2, false))->require_version(6))
.insert(OpcodeInstr::mkfixed(0xd76c >> 2, 14, 2, instr::dump_1c_and(3, "CDEPTHI "), std::bind(exec_cell_depth_i, _1, _2, false))->require_version(6))
.insert(OpcodeInstr::mksimple(0xd770, 16, "CHASHIX ", std::bind(exec_cell_hash_i, _1, 0, true))->require_version(6))
.insert(OpcodeInstr::mksimple(0xd771, 16, "CDEPTHIX ", std::bind(exec_cell_depth_i, _1, 0, true))->require_version(6));
}

void register_cell_ops(OpcodeTable& cp0) {
Expand Down
14 changes: 14 additions & 0 deletions doc/GlobalVersions.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,26 @@ If the parameter is absent from the config, the value is null.
* **6**: `ConfigParam 43` (size limits).

### New TVM instructions

#### Fee calculation
* `GETEXECUTIONPRICE` (`gas_used is_mc - price`) - calculates gas fee.
* `GETSTORAGEPRICE` (`cells bits seconds is_mc - price`) - calculates storage fees (only current StoragePrices entry is used).
* `GETFORWARDPRICE` (`cells bits is_mc - price`) - calculates forward fee.
* `GETPRECOMPILEDGAS` (`- null`) - reserved, currently returns `null`.

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

#### Cell operations
Operations for working with Merkle proofs, where cells can have non-zero level and multiple hashes.
* `CLEVEL` (`cell - level`) - returns level of the cell.
* `CLEVELMASK` (`cell - level_mask`) - returns level mask of the cell.
* `i CHASHI` (`cell - hash`) - returns `i`th hash of the cell.
* `i CDEPTHI` (`cell - depth`) - returns `i`th depth of the cell.
* `CHASHIX` (`cell i - hash`) - returns `i`th hash of the cell.
* `CDEPTHIX` (`cell i - depth`) - returns `i`th depth of the cell.

`i` is in range `0..3`.

### Other changes
* `GLOBALID` gets `ConfigParam 19` from the tuple, not from the config dict. This decreases gas usage.
* `SENDMSG` gets `ConfigParam 24/25` (message prices) from the tuple, not from the config dict, and also uses `ConfigParam 43` to get max_msg_cells.
1 change: 1 addition & 0 deletions test/regression-tests.ans
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Test_Fift_test_fiftext_default 2b0db5d4d4bfbc705b959cc787540d7b3a21a71469eac5475
Test_Fift_test_fixed_default 278a19d56b773102caf5c1fe2997ea6c8d0d9e720eff8503feede6398a197eec
Test_Fift_test_hash_ext_default 686fc5680feca5b3bb207768215b27f6872a95128762dee0d7f2c88bc492d62d
Test_Fift_test_hmap_default c269246882039824bb5822e896c3e6e82ef8e1251b6b251f5af8ea9fb8d05067
Test_Fift_test_levels_default 9fba4a7c98aec9000f42846d6e5fd820343ba61d68f9139dd16c88ccda757cf3
Test_Fift_test_namespaces_default e6419619c51332fb5e8bf22043ef415db686c47fe24f03061e5ad831014e7c6c
Test_Fift_test_rist255_default f4d7558f200a656934f986145c19b1dedbe2ad029292a5a975576d6891e25fc4
Test_Fift_test_sort2_default 9b57d47e6a10e7d1bbb565db35400debf2f963031f434742a702ec76555a5d3a
Expand Down

0 comments on commit 51d30e2

Please sign in to comment.