TolikUSS / tvm-linker

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TVM linker

This repository stores the source code for tvm_linker utility. It takes TVM (https://test.ton.org/tvm.pdf) assembly source code of TON smart contract, compiles it and links its parts, adds standard selector and runtime and stores it into binary TVC file. Also, it can immediately execute a smart contract by emulating the compute phase of TON transaction.

TVM assembly can be generated by one of TONLabs compilers:

Prerequisites

How to build

cd tvm_linker && cargo update && cargo build [--release]

How to use

tvm_linker has several modes of work:

1) Generating a ready-to-deploy contract.

tvm_linker compile [--lib <lib_file>] [--abi-json <abi_file>] [--genkey | --setkey <keyfile>] [-w <workchain_id>] [--debug] <source>

Here source is a name of tvm assembly source file, library is a runtime library file (can be more than one: --lib should be supplied for every file). If --lib option is not specified linker looks for environment variable TVM_LINKER_LIB_PATH, if it is set that path is used to load a library.

If there is an ABI file, it is better to use --abi-json option to supply a contract ABI file. Function ID's are generated according to function signatures in the ABI. If neither -a nor --abi-json option is specified, linker checks whether file source(without extension) + .abi.json exists. If file exists, linker loads ABI from it.

Linker generates an address.tvc file, where address is a hash from initial data and code of the contract.

Linker prints contract address in different formats: raw and user-friendly (testnet and mainnet). Define the workchain ID option -w to generate proper user-friendly address. -1 is used by default.

To generate a new keypair and put the public key to the contract:

tvm_linker compile <source> --genkey <key_file>

where key_file is a name of the file to store public and private keys. The linker will generate 2 files: key_file.pub for public key and key_file for private key.

To load existing keypair use:

tvm_linker compile <source> --setkey <key_file>

2) Decoding of .boc messages prepared externally.

To use this method, call

tvm_linker decode [--tvc] boc-file

If --tvc is omitted, boc-file is a file with a serialized message, otherwise it is a contract tvc file.

3) Preparing an external inbound messages in .boc format.

First, generate a contract as described in 1). Then use message subcommand to create external inbound message in boc format:

tvm_linker message <contract-address> [--init] [--data] [-w]

tvm_linker message <contract-address> [--init] --abi-json <abi_file> --abi-method <method_name> --abi-params {json_with_params} [-w]

contract-address - the name of the compiled contract file without extension. The contract .tvc file should be placed in the current directory.

To create a constructor message with contract's code and data, use --init option.

Additionally, you can add a raw body to the message. Use the --data option:

tvm_linker message <contract-address> --data XXXX...

Instead of XXXX..., specify the necessary message body in hex format.

Or make a message with ABI call using combination of options:

  • --abi-json <abi_file> - path to a .json with contract interface described according to ABI specification;
  • --abi-method <method-name> - name of the contract method to call;
  • --abi-params {<json-string-with-params>} - arguments of the method declared in json like this: {"arg_a": "0x1234", "arg_b": "x12345678"}.

By default, -1 is used as a workchain id in contract address. To use another one, use -w option:

tvm_linker message -w 0

4) Emulating contract execution:

Linker can emulate compute phase of blockchain transaction. It is useful for contract debugging.

tvm_linker test <contract-address> --body XXXX... [--sign key-file] [--trace] [--decode-c6] [--internal <value>] [--src address] [--now unixtime] [-s source-file] [--balance <value>]

Loads contract from file by contract address address and emulates contract call sending external inbound message (by default) with body defined after --body parameter to the contract. XXXX... is a hex string.

If --sign specified, the body will be signed with the private key from key-file file.

Use --trace flag to trace VM execution: stack, registers and gas will be printed after each executed VM command.

Use --decode-c6 to see output actions in user-friendly format.

Use --balance <value> to define account balance in nanograms. It will be available at the bottom of initial stake and in SmartContractInfo tuple from c7 register .

Use --internal to send internal message to the contract with defined nanograms in value. By default, source address in internal message in zero address (0000...0000), to define another address use option --src <address>, where address should be in the format : (i.e. "0:1122...AABB").

Account and message balance can have extended format with extra currencies: { "main": int, "extra": {"i": int, ...} }.

Example: --internal 100000 --src "0:6011b66a47238cf992f1033fe6aff00ce0f850df387ee92468d9c26b5564ba53"

Use --now <unixtime> option to define transaction creation time. By default, current time is used.

Use --bounced flag to emulate bounced internal message, use this flag only with --internal option.

An ABI body can be generated if abi-params, abi-json and abi-method will be used instead of --body XXXX....

If --body is used, contract's public function ids can be encoded by their names using $...$ syntax:$name:[0len][type]$, where name is a name of public function, len - length in chars of the id (if len is bigger than name's length in chars than zeros will be added on the left side to fit required length), type can be x or X - hexadecimal integer in lowercase or uppercase. You have to set -s source option when you use $...$ syntax.

Example:

tvm_linker address test --body 00$main$ -s source //main id will be inserted as decimal string. Dont use this case, just as example
tvm_linker address test --body 00$main:08X$ -s source
tvm_linker address test --body 00$main:X$ -s source
tvm_linker address test --body 00$main:x$ -s source

The --body-from-boc option is analogous to --body but extracts the message body from the specified message boc file.

5) Initialize static variables in compiled contract

tvm_linker init <tvc_file> <data_json> <abi_file>

Updates contract's static state variables (see section data in *.abi.json file) with values defined in data_json argument.

Example:

tvm_linker init contract.tvc '{"var1": 10}' contract.abi.json

6) Disassembler

There are a number of tools under the disasm umbrella:

dump outputs a pseudo-graphical representation of a tree of cells. solidity and fun_c subcommands both disassemble a tvc produced by Solidity and FunC compilers respectively. graphviz produces an output in dot format for generation of graphical DAG representation of a tvc.

More Help

Use tvm_linker --help for detailed description about all options, flags and subcommands.

Input format

As a temporary measure, some LLVM-assembler like input is used. The source code should contain several function types:

  • .selector - contract's entry point. This function should be short.
	.selector
	<code here>
  • .globl - general purpose functions; can be public or private.
	.globl	x
	[.public x]
	.type x, @function
	x:
	<code here>
  • .internal - special functions, which are used only by contract's runtime. There are some wellknown internal functions:

    main_external, main_internal, main_ticktock, main_split, main_merge

Support

Get more documents at docs.ton.dev and check our YouTube Channel for tutorials. Stay tuned.

About

License:Apache License 2.0


Languages

Language:Rust 91.0%Language:Python 4.8%Language:Assembly 3.1%Language:Solidity 1.0%Language:Shell 0.1%Language:Makefile 0.0%