From a06a71ea999454fbb2cbc7dbd84860bc9ec1045d Mon Sep 17 00:00:00 2001 From: neodiX Date: Tue, 11 Jun 2024 15:17:14 +0200 Subject: [PATCH] fix deserialization of MsgAddressInt --- .../java/tlb/types/CommonMsgInfoRelaxed.java | 13 ++- .../org/ton/java/tlb/types/MsgAddress.java | 1 + .../org/ton/java/tlb/types/MsgAddressInt.java | 6 +- .../org/ton/java/tlb/types/VmStackList.java | 12 +++ .../org/ton/java/tlb/types/VmStackValue.java | 26 ++++- .../java/org/ton/java/tlb/types/VmTuple.java | 2 +- .../org/ton/java/tlb/types/VmTupleRef.java | 18 +++- .../ton/java/emulator/GetMethodParams.java | 30 ++++++ .../ton/java/emulator/TestTvmEmulator.java | 96 ++++++++++++++++++- .../org/ton/java/emulator/TvmEmulator.java | 4 +- 10 files changed, 187 insertions(+), 21 deletions(-) create mode 100644 emulator/src/main/java/org/ton/java/emulator/GetMethodParams.java diff --git a/cell/src/main/java/org/ton/java/tlb/types/CommonMsgInfoRelaxed.java b/cell/src/main/java/org/ton/java/tlb/types/CommonMsgInfoRelaxed.java index 1b7059d6..0dd97724 100644 --- a/cell/src/main/java/org/ton/java/tlb/types/CommonMsgInfoRelaxed.java +++ b/cell/src/main/java/org/ton/java/tlb/types/CommonMsgInfoRelaxed.java @@ -6,12 +6,15 @@ /** * int_msg_info$0 ihr_disabled:Bool bounce:Bool bounced:Bool - * src:MsgAddress dest:MsgAddressInt - * value:CurrencyCollection ihr_fee:Grams fwd_fee:Grams - * created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed; + * src:MsgAddress + * dest:MsgAddressInt + * value:CurrencyCollection + * ihr_fee:Grams + * fwd_fee:Grams + * created_lt:uint64 + * created_at:uint32 = CommonMsgInfoRelaxed; *

- * ext_out_msg_info$11 src:MsgAddress dest:MsgAddressExt - * created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed; + * ext_out_msg_info$11 src:MsgAddress dest:MsgAddressExt created_lt:uint64 created_at:uint32 = CommonMsgInfoRelaxed; */ diff --git a/cell/src/main/java/org/ton/java/tlb/types/MsgAddress.java b/cell/src/main/java/org/ton/java/tlb/types/MsgAddress.java index ad493fed..4d896a2a 100644 --- a/cell/src/main/java/org/ton/java/tlb/types/MsgAddress.java +++ b/cell/src/main/java/org/ton/java/tlb/types/MsgAddress.java @@ -27,6 +27,7 @@ static MsgAddress deserialize(CellSlice cs) { int magic = cs.preloadUint(2).intValue(); switch (magic) { case 0b00: { + cs.loadInt(2); return MsgAddressExtNone.builder().build(); } case 0b01: { diff --git a/cell/src/main/java/org/ton/java/tlb/types/MsgAddressInt.java b/cell/src/main/java/org/ton/java/tlb/types/MsgAddressInt.java index fdd008bf..d7869ce7 100644 --- a/cell/src/main/java/org/ton/java/tlb/types/MsgAddressInt.java +++ b/cell/src/main/java/org/ton/java/tlb/types/MsgAddressInt.java @@ -8,11 +8,7 @@ /** * addr_std$10 anycast:(Maybe Anycast) workchain_id:int8 address:bits256 = MsgAddressInt; *

- * addr_var$11 - * anycast:(Maybe Anycast) - * addr_len:(## 9) - * workchain_id:int32 - * address:(bits addr_len) = MsgAddressInt; + * addr_var$11 anycast:(Maybe Anycast) addr_len:(## 9) workchain_id:int32 address:(bits addr_len) = MsgAddressInt; */ public interface MsgAddressInt extends MsgAddress { Cell toCell(); diff --git a/cell/src/main/java/org/ton/java/tlb/types/VmStackList.java b/cell/src/main/java/org/ton/java/tlb/types/VmStackList.java index 26e98f2b..0f8c7b33 100644 --- a/cell/src/main/java/org/ton/java/tlb/types/VmStackList.java +++ b/cell/src/main/java/org/ton/java/tlb/types/VmStackList.java @@ -22,6 +22,12 @@ public class VmStackList { List tos; + /** + * Also knows as serializeTuple() in ton-core web. + * + * @return Cell + */ + public Cell toCell() { Cell list = CellBuilder.beginCell().endCell(); int i = 0; @@ -35,6 +41,12 @@ public Cell toCell() { return list; } + /** + * Also knows as parseTuple() in ton-core web. + * + * @param cs CellSlice + * @return VmStackList + */ public static VmStackList deserialize(CellSlice cs) { List tos = new ArrayList<>(); while (cs.getRefsCount() != 0) { diff --git a/cell/src/main/java/org/ton/java/tlb/types/VmStackValue.java b/cell/src/main/java/org/ton/java/tlb/types/VmStackValue.java index c4841da8..c77c8c80 100644 --- a/cell/src/main/java/org/ton/java/tlb/types/VmStackValue.java +++ b/cell/src/main/java/org/ton/java/tlb/types/VmStackValue.java @@ -3,21 +3,45 @@ import org.ton.java.cell.Cell; import org.ton.java.cell.CellSlice; +/** + * vm_stk_null#00 = VmStackValue; + * vm_stk_tinyint#01 value:int64 = VmStackValue; + * vm_stk_int#0201_ value:int257 = VmStackValue; + * vm_stk_nan#02ff = VmStackValue; + * vm_stk_cell#03 cell:^Cell = VmStackValue; + * cell:^Cell st_bits:(## 10) end_bits:(## 10) { st_bits <= end_bits } st_ref:(#<= 4) end_ref:(#<= 4) { st_ref <= end_ref } = VmCellSlice; + * vm_stk_slice#04 _:VmCellSlice = VmStackValue; + * vm_stk_builder#05 cell:^Cell = VmStackValue; + * vm_stk_cont#06 cont:VmCont = VmStackValue; + * vm_tupref_nil$_ = VmTupleRef 0; + * vm_tupref_single$_ entry:^VmStackValue = VmTupleRef 1; + * vm_tupref_any$_ {n:#} ref:^(VmTuple (n + 2)) = VmTupleRef (n + 2); + * vm_tuple_nil$_ = VmTuple 0; + * vm_tuple_tcons$_ {n:#} head:(VmTupleRef n) tail:^VmStackValue = VmTuple (n + 1); + * vm_stk_tuple#07 len:(## 16) data:(VmTuple len) = VmStackValue; + */ public interface VmStackValue { Cell toCell(); static VmStackValue deserialize(CellSlice cs) { + + if (cs.isSliceEmpty()) { + return null; + } CellSlice c = cs.clone(); + int magic = c.preloadUint(8).intValue(); - int magic2 = c.skipBits(8).preloadUint(8).intValue(); + if (magic == 0x00) { return VmStackValueNull.deserialize(cs); } else if (magic == 0x01) { return VmStackValueTinyInt.deserialize(cs); } else if (magic == 0x02) { + //int magic2 = c.skipBits(8).preloadUint(8).intValue(); return VmStackValueInt.deserialize(cs); + // if (magic2 == 0x01) { // return VmStackValueInt.deserialize(cs); // } else if (magic2 == 0xff) { diff --git a/cell/src/main/java/org/ton/java/tlb/types/VmTuple.java b/cell/src/main/java/org/ton/java/tlb/types/VmTuple.java index e9fc4c78..f4a2d38c 100644 --- a/cell/src/main/java/org/ton/java/tlb/types/VmTuple.java +++ b/cell/src/main/java/org/ton/java/tlb/types/VmTuple.java @@ -29,7 +29,7 @@ public Cell toCell() { public static VmTuple deserialize(CellSlice cs) { return VmTuple.builder() .head(VmTupleRef.deserialize(cs)) - .tail(VmStackValue.deserialize(CellSlice.beginParse(cs.loadRef()))) + .tail(cs.getRefsCount() > 0 ? VmStackValue.deserialize(CellSlice.beginParse(cs.loadRef())) : null) .build(); } } diff --git a/cell/src/main/java/org/ton/java/tlb/types/VmTupleRef.java b/cell/src/main/java/org/ton/java/tlb/types/VmTupleRef.java index 6f118b2d..59ce6104 100644 --- a/cell/src/main/java/org/ton/java/tlb/types/VmTupleRef.java +++ b/cell/src/main/java/org/ton/java/tlb/types/VmTupleRef.java @@ -17,7 +17,7 @@ @Getter @Setter @ToString -public class VmTupleRef { // todo VmTupleRef +public class VmTupleRef { VmStackValue entry; public Cell toCell() { @@ -26,9 +26,17 @@ public Cell toCell() { .endCell(); } - public static VmTupleRef deserialize(CellSlice cs) { - return VmTupleRef.builder() - .entry(VmStackValue.deserialize(CellSlice.beginParse(cs.loadRef()))) - .build(); + public static VmTupleRef deserialize(CellSlice cs) { // more tests are required + if (cs.getRefsCount() == 0) { + return null; + } else if (cs.getRefsCount() == 1) { + return VmTupleRef.builder() + .entry(VmStackValue.deserialize(cs)) + .build(); + } else { + return VmTupleRef.builder() + .entry(VmStackValue.deserialize(CellSlice.beginParse(cs.loadRef()))) + .build(); + } } } diff --git a/emulator/src/main/java/org/ton/java/emulator/GetMethodParams.java b/emulator/src/main/java/org/ton/java/emulator/GetMethodParams.java new file mode 100644 index 00000000..9ad1dfde --- /dev/null +++ b/emulator/src/main/java/org/ton/java/emulator/GetMethodParams.java @@ -0,0 +1,30 @@ +package org.ton.java.emulator; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.ton.java.address.Address; +import org.ton.java.cell.Cell; + +import java.io.Serializable; +import java.math.BigInteger; + +@Builder +@Setter +@Getter +@ToString +public class GetMethodParams implements Serializable { + Cell code; + Cell data; + TvmVerbosityLevel verbosityLevel; + Cell libs; + Address address; + long unixTime; + BigInteger balance; + String randSeed; + long gasLimit; + long methodId; + boolean debugEnabled; +} + diff --git a/emulator/src/test/java/org/ton/java/emulator/TestTvmEmulator.java b/emulator/src/test/java/org/ton/java/emulator/TestTvmEmulator.java index 156164d6..7b6f01b5 100644 --- a/emulator/src/test/java/org/ton/java/emulator/TestTvmEmulator.java +++ b/emulator/src/test/java/org/ton/java/emulator/TestTvmEmulator.java @@ -29,6 +29,7 @@ import java.io.IOException; import java.math.BigInteger; import java.time.Instant; +import java.util.Arrays; import java.util.Collections; import java.util.concurrent.ExecutionException; @@ -140,7 +141,11 @@ public void testTvmEmulatorEmulateRunMethod() { .storeUint(85143, 32) // method-id - seqno .endCell() .toBase64(); - String result = tvmEmulator.emulateRunMethod(1, paramsBoc, Utils.toNano(1).longValue()); + + + Cell c = CellBuilder.beginCell().fromBocBase64(paramsBoc).endCell(); + log.info("c {}", c); + String result = tvmEmulator.emulateRunMethod(paramsBoc.length(), paramsBoc, Utils.toNano(1).longValue()); log.info("result emulateRunMethod: {}", result); // todo - return null } @@ -199,6 +204,58 @@ public void testTvmEmulatorRunGetMethodGetPubKey() { log.info("vmStackList value: {}", pubKey.toString(16)); // pubkey } + @Test + public void testTvmEmulatorRunGetMethodGetPluginList() { + String stackSerialized = VmStack.builder() + .depth(0) + .stack(VmStackList.builder() + .tos(Lists.emptyList()) + .build()) + .build() + .toCell().toBase64(); + + String result = tvmEmulator.runGetMethod( + 107653, // CRC-16/XMODEM of get_plugin_list + stackSerialized); + log.info("result runGetMethod: {}", result); + + GetMethodResult methodResult = gson.fromJson(result, GetMethodResult.class); + log.info("methodResult: {}", methodResult); + log.info("methodResult stack: {}", methodResult.getStack()); + + Cell cellResult = CellBuilder.beginCell().fromBocBase64(methodResult.getStack()).endCell(); + log.info("cellResult {}", cellResult); + VmStackValueTuple tuple = VmStackValueTuple.deserialize(CellSlice.beginParse(cellResult)); + log.info("tuple {}", tuple); + } + + @Test + public void testTvmEmulatorRunGetMethodIsPluginInstalled() { + String stackSerialized = VmStack.builder() + .depth(0) + .stack(VmStackList.builder() + .tos(Arrays.asList( + VmStackValueTinyInt.builder().value(BigInteger.ZERO).build(), + VmStackValueTinyInt.builder().value(BigInteger.ZERO).build())) + .build()) + .build() + .toCell().toBase64(); + + String result = tvmEmulator.runGetMethod( + 76407, // CRC-16/XMODEM of is_plugin_installed(int wc, int addr_hash) + stackSerialized); + log.info("result runGetMethod: {}", result); + + GetMethodResult methodResult = gson.fromJson(result, GetMethodResult.class); + log.info("methodResult: {}", methodResult); + log.info("methodResult stack: {}", methodResult.getStack()); + + Cell cellResult = CellBuilder.beginCell().fromBocBase64(methodResult.getStack()).endCell(); + log.info("cellResult {}", cellResult); + VmStackValueTuple tuple = VmStackValueTuple.deserialize(CellSlice.beginParse(cellResult)); + log.info("tuple {}", tuple); + } + @Test public void testTvmEmulatorRunGetMethodGetPubKeyShortVersion() { log.info("contract's pubKey: {}", tvmEmulator.runGetPublicKey()); // pubkey @@ -235,7 +292,12 @@ public void testTvmEmulatorSendExternalMessage() { SendExternalMessageResult result = gson.fromJson(resultBoc, SendExternalMessageResult.class); log.info("result sendExternalMessage, exitCode: {}", result.getVm_exit_code()); + log.info("result sendExternalMessage, actions: {}", result.getActions()); log.info("seqno value: {}", tvmEmulator.runGetSeqNo()); + OutList actions = OutList.deserialize( + CellSlice.beginParse( + CellBuilder.beginCell().fromBocBase64(result.getActions()).endCell())); + log.info("parsed actions {}", actions); } @Test @@ -333,6 +395,25 @@ public void testTvmEmulatorSendExternalMessageCustom() throws IOException, Execu result = gson.fromJson(resultBoc, SendExternalMessageResult.class); log.info("result sendExternalMessage, exitCode: {}", result.getVm_exit_code()); + + + // still to review + String stackSerialized = VmStack.builder() + .depth(2) + .stack(VmStackList.builder() + .tos(Arrays.asList( + VmStackValueTinyInt.builder().value(BigInteger.ZERO).build(), + VmStackValueTinyInt.builder().value(BigInteger.TEN).build())) + .build()) + .build() + .toCell() + .toBase64(); + + // is_plugin_installed + String resultStr = tvmEmulator.runGetMethod( + 76407, // CRC-16/XMODEM of is_plugin_installed(int wc, int addr_hash) + stackSerialized); + log.info("result runGetMethod (is_plugin_installed): {}", resultStr); } @Test @@ -390,7 +471,6 @@ public void testTvmEmulatorSendInternalMessageCustomContract() throws IOExceptio log.info("resultBoc {}", resultBoc); SendExternalMessageResult result = gson.fromJson(resultBoc, SendExternalMessageResult.class); log.info("result sendInternalMessage, exitCode: {}", result.getVm_exit_code()); - } @Test @@ -410,7 +490,17 @@ public void testTvmEmulatorSendInternalMessage() { @Test public void testTvmEmulatorSetPrevBlockInfo() { -// assertTrue(tvmEmulator.setPrevBlockInfo()); + String infoBocBase64 = ""; + // must be tuple, below won't work +// BlkPrevInfo blkPrevInfo = BlkPrevInfo.builder() +// .prev1(ExtBlkRef.builder() +// .seqno(10) +// .endLt(BigInteger.valueOf(500000000)) +// .fileHash(BigInteger.ONE) +// .rootHash(BigInteger.TEN) +// .build()) +// .build(); + assertTrue(tvmEmulator.setPrevBlockInfo(infoBocBase64)); } diff --git a/emulator/src/test/java/org/ton/java/emulator/TvmEmulator.java b/emulator/src/test/java/org/ton/java/emulator/TvmEmulator.java index 2b689ac5..58c23f4f 100644 --- a/emulator/src/test/java/org/ton/java/emulator/TvmEmulator.java +++ b/emulator/src/test/java/org/ton/java/emulator/TvmEmulator.java @@ -129,7 +129,9 @@ public boolean setLibs(String libsBoc) { } /** - * C7 tlb-scheme: + * Prepares the c7 tuple (virtual machine context) for a compute phase of a transaction. + *

+ * C7 tlb-scheme FYI: *

* smc_info#076ef1ea * actions:uint16