mirror of
				https://github.com/ton-blockchain/ton
				synced 2025-03-09 15:40:10 +00:00 
			
		
		
		
	Add TVM instructions for working with nonzero-level cells (#880)
Co-authored-by: SpyCheese <mikle98@yandex.ru>
This commit is contained in:
		
							parent
							
								
									64b04e46d7
								
							
						
					
					
						commit
						51d30e2f2b
					
				
					 6 changed files with 156 additions and 1 deletions
				
			
		| 
						 | 
					@ -813,6 +813,12 @@ x{D761} @Defop LDONES
 | 
				
			||||||
x{D762} @Defop LDSAME
 | 
					x{D762} @Defop LDSAME
 | 
				
			||||||
x{D764} @Defop SDEPTH
 | 
					x{D764} @Defop SDEPTH
 | 
				
			||||||
x{D765} @Defop CDEPTH
 | 
					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
 | 
					// continuation / flow control primitives
 | 
				
			||||||
x{D8} dup @Defop EXECUTE @Defop CALLX
 | 
					x{D8} dup @Defop EXECUTE @Defop CALLX
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -163,3 +163,7 @@ TEST(Fift, test_bls) {
 | 
				
			||||||
TEST(Fift, test_bls_ops) {
 | 
					TEST(Fift, test_bls_ops) {
 | 
				
			||||||
  run_fift("bls_ops.fif");
 | 
					  run_fift("bls_ops.fif");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TEST(Fift, test_levels) {
 | 
				
			||||||
 | 
					  run_fift("levels.fif");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										75
									
								
								crypto/test/fift/levels.fif
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								crypto/test/fift/levels.fif
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
| 
						 | 
					@ -1391,6 +1391,55 @@ int exec_slice_depth(VmState* st) {
 | 
				
			||||||
  return 0;
 | 
					  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) {
 | 
					void register_cell_deserialize_ops(OpcodeTable& cp0) {
 | 
				
			||||||
  using namespace std::placeholders;
 | 
					  using namespace std::placeholders;
 | 
				
			||||||
  cp0.insert(OpcodeInstr::mksimple(0xd0, 8, "CTOS", exec_cell_to_slice))
 | 
					  cp0.insert(OpcodeInstr::mksimple(0xd0, 8, "CTOS", exec_cell_to_slice))
 | 
				
			||||||
| 
						 | 
					@ -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(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(0xd762, 16, "LDSAME", std::bind(exec_load_same, _1, "LDSAME", -1)))
 | 
				
			||||||
      .insert(OpcodeInstr::mksimple(0xd764, 16, "SDEPTH", exec_slice_depth))
 | 
					      .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) {
 | 
					void register_cell_ops(OpcodeTable& cp0) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,12 +69,26 @@ If the parameter is absent from the config, the value is null.
 | 
				
			||||||
* **6**: `ConfigParam 43` (size limits).
 | 
					* **6**: `ConfigParam 43` (size limits).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### New TVM instructions
 | 
					### New TVM instructions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Fee calculation
 | 
				
			||||||
* `GETEXECUTIONPRICE` (`gas_used is_mc - price`) - calculates gas fee.
 | 
					* `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).
 | 
					* `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.
 | 
					* `GETFORWARDPRICE` (`cells bits is_mc - price`) - calculates forward fee.
 | 
				
			||||||
* `GETPRECOMPILEDGAS` (`- null`) - reserved, currently returns `null`.
 | 
					* `GETPRECOMPILEDGAS` (`- null`) - reserved, currently returns `null`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`gas_used`, `cells`, `bits`, `time_delta` are integers in range `0..2^63-1`.
 | 
					`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
 | 
					### Other changes
 | 
				
			||||||
* `GLOBALID` gets `ConfigParam 19` from the tuple, not from the config dict. This decreases gas usage.
 | 
					* `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.
 | 
					* `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.
 | 
				
			||||||
| 
						 | 
					@ -18,6 +18,7 @@ Test_Fift_test_fiftext_default 2b0db5d4d4bfbc705b959cc787540d7b3a21a71469eac5475
 | 
				
			||||||
Test_Fift_test_fixed_default 278a19d56b773102caf5c1fe2997ea6c8d0d9e720eff8503feede6398a197eec
 | 
					Test_Fift_test_fixed_default 278a19d56b773102caf5c1fe2997ea6c8d0d9e720eff8503feede6398a197eec
 | 
				
			||||||
Test_Fift_test_hash_ext_default 686fc5680feca5b3bb207768215b27f6872a95128762dee0d7f2c88bc492d62d
 | 
					Test_Fift_test_hash_ext_default 686fc5680feca5b3bb207768215b27f6872a95128762dee0d7f2c88bc492d62d
 | 
				
			||||||
Test_Fift_test_hmap_default c269246882039824bb5822e896c3e6e82ef8e1251b6b251f5af8ea9fb8d05067
 | 
					Test_Fift_test_hmap_default c269246882039824bb5822e896c3e6e82ef8e1251b6b251f5af8ea9fb8d05067
 | 
				
			||||||
 | 
					Test_Fift_test_levels_default 9fba4a7c98aec9000f42846d6e5fd820343ba61d68f9139dd16c88ccda757cf3
 | 
				
			||||||
Test_Fift_test_namespaces_default e6419619c51332fb5e8bf22043ef415db686c47fe24f03061e5ad831014e7c6c
 | 
					Test_Fift_test_namespaces_default e6419619c51332fb5e8bf22043ef415db686c47fe24f03061e5ad831014e7c6c
 | 
				
			||||||
Test_Fift_test_rist255_default f4d7558f200a656934f986145c19b1dedbe2ad029292a5a975576d6891e25fc4
 | 
					Test_Fift_test_rist255_default f4d7558f200a656934f986145c19b1dedbe2ad029292a5a975576d6891e25fc4
 | 
				
			||||||
Test_Fift_test_sort2_default 9b57d47e6a10e7d1bbb565db35400debf2f963031f434742a702ec76555a5d3a
 | 
					Test_Fift_test_sort2_default 9b57d47e6a10e7d1bbb565db35400debf2f963031f434742a702ec76555a5d3a
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue