소스 검색

Document how Solana contract storage works

It makes more sense to merge the language status wit the language page,
and have a separate page for the target-specific documentation.

Signed-off-by: Sean Young <sean@mess.org>
Sean Young 4 년 전
부모
커밋
1032eaee3b
5개의 변경된 파일217개의 추가작업 그리고 224개의 파일을 삭제
  1. 1 2
      docs/index.rst
  2. 23 1
      docs/language.rst
  3. 5 155
      docs/running.rst
  4. 0 66
      docs/status.rst
  5. 188 0
      docs/targets.rst

+ 1 - 2
docs/index.rst

@@ -19,7 +19,6 @@ for `Parity Substrate <https://substrate.dev/>`_,
 
 Solang aims for source file compatibility with the Ethereum EVM Solidity compiler,
 version 0.7. Where differences exists, this is noted in the :ref:`language documentation <language>`.
-Also, check our :ref:`status` page.
 The repository can be found on `github <https://github.com/hyperledger-labs/solang>`_
 and we have a `channel on chat.hyperledger.org <https://chat.hyperledger.org/channel/solang>`_.
 
@@ -28,9 +27,9 @@ and we have a `channel on chat.hyperledger.org <https://chat.hyperledger.org/cha
    :caption: Contents:
 
    installing
-   status
    running
    language
+   targets
    optimizer
    extension
    examples

+ 23 - 1
docs/language.rst

@@ -5,13 +5,35 @@ Solidity Language
 
 The Solidity language supported by Solang aims to be compatible with the latest
 `Ethereum Foundation Solidity Compiler <https://github.com/ethereum/solidity/>`_,
-version 0.7 with some caveats, please check out our :ref:`status` page.
+version 0.7 with some caveats.
 
 .. note::
 
   Where differences exist between different targets or the Ethereum Foundation Solidity
   compiler, this is noted in boxes like these.
 
+Brief Language Status
+---------------------
+
+As with any new project, bugs are possible. Please report any issues you may find to github.
+
+Differences:
+
+- ``immutable`` is not supported. Note this is impossible to implement on any than chain other than Ethereum; this is purely an ethereum feature
+- libraries are always statically linked into the contract code
+- Solang generates WebAssembly or BPF rather than EVM. This means that the ``assembly {}``
+  statement using EVM instructions is not supported
+
+Unique features to Solang:
+
+- Solang can target different blockchains and some features depending on the target.
+  For example, Parity Substrate uses a different ABI encoding and allows constructors
+  to be overloaded.
+- Events can be declared outside of contracts
+- Base contracts can be declared in any order
+- There is a ``print()`` function for debugging
+- Strings can be formatted with python style format string, which is useful for debugging: ``print("x = {}".format(x));``
+
 Solidity Source File Structure
 ------------------------------
 

+ 5 - 155
docs/running.rst

@@ -1,5 +1,5 @@
-Running Solang
-==============
+Using Solang on the command line
+================================
 
 The Solang compiler is run on the command line. The solidity source file
 names are provided as command line arguments; the output is an optimized
@@ -11,8 +11,9 @@ The following targets are supported right now:
 `Ethereum ewasm <https://github.com/ewasm/design>`_, and
 `Sawtooth Sabre <https://github.com/hyperledger/sawtooth-sabre>`_.
 
-Using Solang on the command line
---------------------------------
+
+Usage
+-----
 
 Usage:
 
@@ -129,154 +130,3 @@ On Windows, you need to specify absolute paths:
 .. code-block:: text
 
 	docker run --rm -it -v C:\Users\User:/sources hyperledgerlabs/solang -o /sources /sources/flipper.sol
-
-
-Using Solang with Substrate
----------------------------
-
-Solang builds contracts for Substrate by default. There is an solidity example
-which can be found in the `examples <https://github.com/hyperledger-labs/solang/tree/main/examples>`_
-directory. Write this to flipper.sol and run:
-
-.. code-block:: bash
-
-  solang --target substrate flipper.sol
-
-Now you should have a file called ``flipper.contract``. The file contains both the ABI and contract wasm.
-It can be used directly in the
-`Polkadot UI <https://substrate.dev/substrate-contracts-workshop/#/0/deploying-your-contract?id=putting-your-code-on-the-blockchain>`_, as if the contract was written in ink!.
-
-Using Solang with Solana
-------------------------
-
-The `Solana <https://www.solana.com/>`_ target is new and is limited right now, not all types are implemented
-and other functionality is incomplete. However, the
-`flipper example <https://github.com/hyperledger-labs/solang/tree/main/examples/flipper.sol>`_
-can be used.
-
-.. code-block:: bash
-
-  solang --target solana flipper.sol -v
-
-This will produce two files called `flipper.abi` and `flipper.so`. The first is an ethereum style abi file and the latter being
-the ELF BPF shared object which can be deployed on Solana.
-
-Solana has execution model which allows one program to interact with multiple accounts. Those accounts can
-be used for different purposes. In Solang's case, each time the contract is executed, it needs two accounts.
-The first account is for the `return data`, i.e. either the ABI encoded
-return values or the revert buffer. The second account is to hold the contract storage variables.
-
-The output of the compiler will tell you how large the second account needs to be. For the `flipper.sol` example,
-the output contains *"info: contract flipper uses exactly 9 bytes account data"*. This means the second account
-should be exactly 9 bytes; anything larger is wasted. If the output is
-*"info: contract store uses at least 168 bytes account data"* then some storage elements are dynamic, so the size
-depends on the data stored. For example there could be a ``string`` type, and storage depends on the length of
-the string. The minimum is 168 bytes, but storing any non-zero-length dynamic types will fail.
-
-If either account is too small, the transaction will fail with the error *account data too small for instruction*.
-
-Before any function on a smart contract can be used, the constructor must be first be called. This ensures that
-the constructor as declared in the solidity code is executed, and that the contract storage account is
-correctly initialized. To call the constructor, abi encode (using ethereum abi encoding) the constructor
-arguments, and pass in two accounts to the call, the 2nd being the contract storage account.
-
-Once that is done, any function on the contract can be called. To do that, abi encode the function call,
-pass this as input, and provide two accounts on the call. The second account must be the same contract
-storage account as used in the constructor. If there are any return values for the function, they
-are stored in the first return data account. The first 8 bytes is a 64 bits length, followed by the
-data itself. You can pass this into an ethereum abi decoder to get the expected return values.
-
-There is `an example of this written in node <https://github.com/hyperledger-labs/solang/tree/main/integration/solana>`_.
-
-Using Solang with Sawtooth Sabre
---------------------------------
-
-When using Solang on Sawtooth Sabre, the constructor and function calls must be encoded with Ethereum ABI encoding.
-This can be done in different ways. In this guide we use `ethabi <https://github.com/paritytech/ethabi>`_. This can
-be installed using cargo:
-
-.. code-block:: bash
-
-  cargo install ethabi-cli
-
-In order to abi encode the calls, we need the abi for the contract. Let's compile flipper.sol for Sabre:
-
-.. code-block:: bash
-
-  solang --target sabre --verbose flipper.sol
-
-We now have a file ``flipper.wasm`` and ``flipper.abi``. To deploy this, we need to create the constructor
-ABI encoding. Unfortunately ethabi already falls short here; we cannot encode constructor calls using the cli
-tools. However we can work round this by specify the constructor arguments explicitly. Note that if the
-constructor does not take any arguments, then the constructor data should be empty (0 bytes). So, since the
-constructor in flipper.sol takes a single bool, create it like so:
-
-.. code-block:: bash
-
-  ethabi encode params -v bool true | xxd -r -p > constructor
-
-For flipping the value, create it so:
-
-.. code-block:: bash
-
-  ethabi encode function flipper.abi flip | xxd -r -p  > flip
-
-You'll also need a yaml file with the following contents. Save it to flipper.yaml.
-
-.. code-block:: yaml
-
-  name: flipper
-  version: '1.0'
-  wasm: flipper.wasm
-  inputs:
-  - '12cd3c'
-  outputs:
-  - '12cd3c'
-
-Now we have to start the Sawtooth Sabre environment. First clone the
-`Sawtooth Sabre github repo <https://github.com/hyperledger/sawtooth-sabre/>`_ and then run:
-
-.. code-block:: bash
-
-  docker-compose -f docker-compose-installed.yaml up --build
-
-Now enter the sabre-cli container:
-
-.. code-block:: bash
-
-  docker exec -it sabre-cli bash
-
-To create the flipper contract, run the following:
-
-.. code-block:: bash
-
-  sabre cr --create flipper --owner $(cat /root/.sawtooth/keys/root.pub) --url http://rest-api:9708
-  sabre upload --filename flipper.yaml --url http://rest-api:9708
-  sabre ns --create 12cd3c --url http://rest-api:9708 --owner $(cat /root/.sawtooth/keys/root.pub)
-  sabre perm 12cd3c flipper --read --write --url http://rest-api:9708
-
-To run the constructor, run:
-
-.. code-block:: bash
-
-   sabre exec --contract flipper:1.0 --payload  ./constructor --inputs 12cd3c  --outputs 12cd3c --url http://rest-api:9708
-
-Lastly, to run the flip function:
-
-.. code-block:: bash
-
-  sabre exec --contract flipper:1.0 --payload  ./flip --inputs 12cd3c  --outputs 12cd3c --url http://rest-api:9708
-
-.. warning::
-
-  Returning values from Solidity is not yet implemented, and neither is ``revert()``. If you
-  attempt to call a function which returns a value, it will fail.
-
-Using Solang with Hyperledger Burrow
-------------------------------------
-
-In Burrow, Solang is used transparently by the ``burrow deploy`` tool if it is given the ``--wasm`` argument.
-When building and deploying a Solidity contract, rather than running the ``solc`` compiler, it will run
-the ``solang`` compiler and deploy it as a wasm contract.
-
-This is documented in the `burrow documentation <https://hyperledger.github.io/burrow/#/reference/wasm>`_.

+ 0 - 66
docs/status.rst

@@ -1,66 +0,0 @@
-.. _status:
-
-Status
-======
-
-Solidity Language Status
-------------------------
-
-Solang is source compatible with the
-`Ethereum Foundation Solidity Compiler <https://github.com/ethereum/solidity/>`_
-version 0.7, with some caveats. Many language features have only recently been
-implemented, and have many unit tests. As with any new project, bugs are possible.
-Please report any issues you may find to github.
-
-Differences:
-
-- ``immutable`` is not supported. Note this is impossible to implement on any than chain other than Ethereum; this is purely an ethereum feature
-- libraries are always statically linked into the contract code
-- Solang generates WebAssembly or BPF rather than EVM. This means that the ``assembly {}``
-  statement using EVM instructions is not supported
-
-Unique features to Solang:
-
-- Solang can target different blockchains and some features depending on the target.
-  For example, Parity Substrate uses a different ABI encoding and allows constructors
-  to be overloaded.
-- Events can be declared outside of contracts
-- Base contracts can be declared in any order
-- There is a ``print()`` function for debugging
-- Strings can be formatted with python style format string, which is useful for debugging: ``print("x = {}".format(x));``
-
-Target Status
--------------
-
-Parity Substrate
-________________
-
-Solang works with Parity Substrate 2.0. This target is the most mature and has received the most testing so far.
-
-Solana
-______
-
-Solang has a new target for `Solana <https://www.solana.com/>`_. This is in early stages right now, however it is
-under active development.
-
-ewasm
-_____
-
-ewasm has been tested with `Hyperledger Burrow <https://github.com/hyperledger/burrow>`_.
-Please use the latest master version of burrow, as ewasm support is still maturing in Burrow.
-
-Some language features have not been fully implemnented yet on ewasm:
-
-- The built in function ``abi.encodePacked()``
-- Contract storage variables types ``string``, ``bytes`` and function types are not implemented
-
-Hyperledger Sawtooth
-____________________
-
-This is merely a proof-of-concept target, and has seen very little testing. On sawtooth,
-many Solidity concepts are impossible to implement:
-
-- Return values from contract calls
-- Calling other contracts
-- Value transfers
-- Instantiating contracts

+ 188 - 0
docs/targets.rst

@@ -0,0 +1,188 @@
+Target Specific
+===============
+
+
+Parity Substrate
+________________
+
+Solang works with Parity Substrate 3.0. This target is the most mature and has received the most testing so far.
+
+The Parity Substrate has the following differences to Ethereum Solidity:
+
+- The address type is 32 bytes, not 20 bytes
+- An address literal has to be specified using the ``address"5GBWmgdFAMqm8ZgAHGobqDqX6tjLxJhv53ygjNtaaAn3sjeZ"`` syntax
+- ABI encoding and decoding is done using the `SCALE <https://substrate.dev/docs/en/overview/low-level-data-format>`_ encoding
+- Multiple constructors are allowed, and can be overloaded
+
+There is an solidity example which can be found in the
+`examples <https://github.com/hyperledger-labs/solang/tree/main/examples>`_
+directory. Write this to flipper.sol and run:
+
+.. code-block:: bash
+
+  solang --target substrate flipper.sol
+
+Now you should have a file called ``flipper.contract``. The file contains both the ABI and contract wasm.
+It can be used directly in the
+`Polkadot UI <https://substrate.dev/substrate-contracts-workshop/#/0/deploying-your-contract?id=putting-your-code-on-the-blockchain>`_, as if the contract was written in ink!.
+
+
+Solana
+______
+
+The Solana target requires `Solana <https://www.solana.com/>`_ 1.5.0 or later. This target is in the early stages right now,
+however it is under active development. All data types are supported, but the builtin functions, external calls, and constructor calls
+have not been implemented yet. This is how to build your Solidity for Solana:
+
+.. code-block:: bash
+
+  solang --target solana flipper.sol -v
+
+This will produce two files called `flipper.abi` and `flipper.so`. The first is an ethereum style abi file and the latter being
+the ELF BPF shared object which can be deployed on Solana.
+
+The contract storage model in Solana is different from Ethereum; it is consists of a contigious piece of memory, which can be
+accessed directly from the smart contract. This means that there are no `storage slots`, and that a `mapping` must be implemented
+using a simple hashmap. The same hashmap is used for fixed-length arrays which are a larger than 1kb. So, if you declare an
+contract storage array of ``int[10000]``, then this is implemented using a hashmap.
+
+Solana has execution model which allows one program to interact with multiple accounts. Those accounts can
+be used for different purposes. In Solang's case, each time the contract is executed, it needs two accounts.
+The first account is for the `return data`, i.e. either the ABI encoded
+return values or the revert buffer. The second account is to hold the contract storage variables.
+
+The output of the compiler will tell you how large the second account needs to be. For the `flipper.sol` example,
+the output contains *"info: contract flipper uses exactly 9 bytes account data"*. This means the second account
+should be exactly 9 bytes; anything larger is wasted. If the output is
+*"info: contract store uses at least 168 bytes account data"* then some storage elements are dynamic, so the size
+depends on the data stored. For example there could be a ``string`` type, and storage depends on the length of
+the string. The minimum is 168 bytes, but storing any non-zero-length dynamic types will fail.
+
+If either account is too small, the transaction will fail with the error *account data too small for instruction*.
+
+Before any function on a smart contract can be used, the constructor must be first be called. This ensures that
+the constructor as declared in the solidity code is executed, and that the contract storage account is
+correctly initialized. To call the constructor, abi encode (using ethereum abi encoding) the constructor
+arguments, and pass in two accounts to the call, the 2nd being the contract storage account.
+
+Once that is done, any function on the contract can be called. To do that, abi encode the function call,
+pass this as input, and provide two accounts on the call. The second account must be the same contract
+storage account as used in the constructor. If there are any return values for the function, they
+are stored in the first return data account. The first 8 bytes is a 64 bits length, followed by the
+data itself. You can pass this into an ethereum abi decoder to get the expected return values.
+
+There is `an example of this written in node <https://github.com/hyperledger-labs/solang/tree/main/integration/solana>`_.
+
+Hyperledger Burrow (ewasm)
+__________________________
+
+The ewasm specification is not finalized yet. There is no `create2` or `chainid` call, and the keccak256 precompile
+contract has not been finalized yet.
+
+In Burrow, Solang is used transparently by the ``burrow deploy`` tool if it is given the ``--wasm`` argument.
+When building and deploying a Solidity contract, rather than running the ``solc`` compiler, it will run
+the ``solang`` compiler and deploy it as a wasm contract.
+
+This is documented in the `burrow documentation <https://hyperledger.github.io/burrow/#/reference/wasm>`_.
+
+ewasm has been tested with `Hyperledger Burrow <https://github.com/hyperledger/burrow>`_.
+Please use the latest master version of burrow, as ewasm support is still maturing in Burrow.
+
+Some language features have not been fully implemented yet on ewasm:
+
+- The built in function ``abi.encodePacked()``
+- Contract storage variables types ``string``, ``bytes`` and function types are not implemented
+
+Hyperledger Sawtooth
+____________________
+
+This is merely a proof-of-concept target, and has seen very little testing. Unless anyone is interested in
+maintaining this target, it is likely to be removed. On sawtooth, many Solidity concepts are impossible to implement:
+
+- Return values from contract calls
+- Calling other contracts
+- Value transfers
+- Instantiating contracts
+
+When using Solang on Sawtooth Sabre, the constructor and function calls must be encoded with Ethereum ABI encoding.
+This can be done in different ways. In this guide we use `ethabi <https://github.com/paritytech/ethabi>`_. This can
+be installed using cargo:
+
+.. code-block:: bash
+
+  cargo install ethabi-cli
+
+In order to abi encode the calls, we need the abi for the contract. Let's compile flipper.sol for Sabre:
+
+.. code-block:: bash
+
+  solang --target sabre --verbose flipper.sol
+
+We now have a file ``flipper.wasm`` and ``flipper.abi``. To deploy this, we need to create the constructor
+ABI encoding. Unfortunately ethabi already falls short here; we cannot encode constructor calls using the cli
+tools. However we can work round this by specify the constructor arguments explicitly. Note that if the
+constructor does not take any arguments, then the constructor data should be empty (0 bytes). So, since the
+constructor in flipper.sol takes a single bool, create it like so:
+
+.. code-block:: bash
+
+  ethabi encode params -v bool true | xxd -r -p > constructor
+
+For flipping the value, create it so:
+
+.. code-block:: bash
+
+  ethabi encode function flipper.abi flip | xxd -r -p  > flip
+
+You'll also need a yaml file with the following contents. Save it to flipper.yaml.
+
+.. code-block:: yaml
+
+  name: flipper
+  version: '1.0'
+  wasm: flipper.wasm
+  inputs:
+  - '12cd3c'
+  outputs:
+  - '12cd3c'
+
+Now we have to start the Sawtooth Sabre environment. First clone the
+`Sawtooth Sabre github repo <https://github.com/hyperledger/sawtooth-sabre/>`_ and then run:
+
+.. code-block:: bash
+
+  docker-compose -f docker-compose-installed.yaml up --build
+
+Now enter the sabre-cli container:
+
+.. code-block:: bash
+
+  docker exec -it sabre-cli bash
+
+To create the flipper contract, run the following:
+
+.. code-block:: bash
+
+  sabre cr --create flipper --owner $(cat /root/.sawtooth/keys/root.pub) --url http://rest-api:9708
+  sabre upload --filename flipper.yaml --url http://rest-api:9708
+  sabre ns --create 12cd3c --url http://rest-api:9708 --owner $(cat /root/.sawtooth/keys/root.pub)
+  sabre perm 12cd3c flipper --read --write --url http://rest-api:9708
+
+To run the constructor, run:
+
+.. code-block:: bash
+
+   sabre exec --contract flipper:1.0 --payload  ./constructor --inputs 12cd3c  --outputs 12cd3c --url http://rest-api:9708
+
+Lastly, to run the flip function:
+
+.. code-block:: bash
+
+  sabre exec --contract flipper:1.0 --payload  ./flip --inputs 12cd3c  --outputs 12cd3c --url http://rest-api:9708
+
+.. warning::
+
+  For the Sawtooth target,
+  returning values from Solidity is not yet implemented, and neither is ``revert()``. If you
+  attempt to call a function which returns a value, it will fail.
+