From 7a3b08fdc7b004f9f7d04ab6093e2a71dd9da3e4 Mon Sep 17 00:00:00 2001 From: radrow Date: Mon, 2 Mar 2020 12:56:52 +0100 Subject: [PATCH] Moved out AEVM ABI --- docs/aevm_01_abi.md | 230 -------------------------------------------- docs/sophia.md | 32 +----- 2 files changed, 1 insertion(+), 261 deletions(-) delete mode 100644 docs/aevm_01_abi.md diff --git a/docs/aevm_01_abi.md b/docs/aevm_01_abi.md deleted file mode 100644 index 73e6760..0000000 --- a/docs/aevm_01_abi.md +++ /dev/null @@ -1,230 +0,0 @@ -## The Sophia\_AEVM\_01 ABI - -### Byte code - -The byte code contains meta data about the original sophia source -code. - -#### Meta data -The byte code contains meta data for the contract. -- source_code_hash - a Blake2b hash of the source code string of the contract -- type_info - see Type information below -- byte_code - the actual byte code - -The layout of the encoding can be found -[here](https://github.com/aeternity/protocol/blob/master/serializations.md#sophia-byte-code). -The encoding is tagged with the compiler version. - -#### Type information -The type information of each function is encoded in the meta data. The function -hash depends both on the function name and the type signature of the function. -The function hash is also the identifier of a function when calling a contract. -In this way, the function prototype in the calling function gets some level of -type verification. - -The type information contains: -- fun_hash - A Blake2b hash of the function name and the function types -- fun_name - The function name as a string -- arg_type - The vm encoded typerep of the argument (as a tuple) of the function -- out_type - The vm encoded typerep of the return type of the function - -### Memory layout - -Sophia values are 256-bit words. In case of unboxed types (`int`, -`address`, and `bool`) this is simply the value. For boxed types -such as tuples and (non-empty) lists, the word is a pointer into the heap -(memory). - -More precisely - -- Unboxed types are represented as a single big endian 256-bit (32 bytes) word. - Booleans are represented as 0 for `false` and 1 for `true`. The empty list is - represented as an unboxed -1. In memory maps are represented by an unboxed - unique identifier. The contents of the map is stored separately in the VM - state. - -- Boxed types are represented as a 256-bit pointer to a contiguous sequence of - words, called a *heap object*, on the heap. - - | Value/Type | Heap object | - | --- | --- | - | Tuple | The value of each component in left-to-right order. | - | String | The length (number of bytes), followed by as many words as required to store the character data, padded on the right with 0. | - | | | - - The following types are represented in terms of other types: - - - - - - - - - - - - -
TypeRepresentation
Non-empty listA pair of the head and the tail.
RecordA tuple of the field values.
Data typeA tuple where the first component is a constructor - tag (starting with 0 for the first constructor), and the following - components are the constructor arguments. For instance, for

- datatype zeroOrTwo = Zero | Two(int, int)

- Zero is encoded as a singleton tuple (0) and - Two(a, b) as the triple (1, a, b). -
SignatureA pair of two 256-bit words.
Option typesdatatype option('a) = None | Some('a).
ttldatatype ttl = RelativeTTL(int) | FixedTTL(int)
Type representations - When types need to be encoded as data, they are represented as the following datatype

-
-
-        datatype typerep = Word  // any unboxed type
-                         | String
-                         | List(typerep)
-                         | Tuple(list(typerep))
-                         | Datatype(list(list(typerep)))
-                         | TypeRep
-                         | Map(typerep, typerep)
-      
- The argument to the Datatype constructor is the list of type - representations of the constructor arguments. -
- -### Encoding Sophia values as binaries - -When communicating Sophia values between a contract and the outside world they -are encoded as a binary containing a heap whose first word is the encoded value -(except in the case of maps, see below). For example, the value `("main", (1, 2, 3))` -can be encoded as -``` -Word 0 1 2 3 4 5 6 7 -Addr 0x00 0x20 0x40 0x60 0x80 0xA0 0xC0 0xE0 -Value 0x20 0x60 0xA0 4 "main" 1 2 3 -``` -where `"main"` is the 32 byte word obtained by right padding the string -`"main"` with zeroes. - -Note that the order of the heap objects on the heap is unspecified. Another -valid encoding of the same value is -``` -Word 0 1 2 3 4 5 6 7 -Addr 0x00 0x20 0x40 0x60 0x80 0xA0 0xC0 0xE0 -Value 0x60 4 "main" 0x20 0xA0 1 2 3 -``` - -A canonical binary representation is obtained by storing heap objects in -depth-first left-to-right order (as in the first example). This is the -representation used in map keys. - -#### Binary encoding of Sophia maps - -In memory, maps are represented by their unique identifier, but in binary -encodings the identifier is replaced by a boxed representation with a heap -object of the shape -``` - MapSize (N) - KeySize1 - +----------+ - | Key1 | - +----------+ - ValSize1 - +----------+ - | Val1 | - +----------+ - ... - KeySizeN - +----------+ - | KeyN | - +----------+ - ValSizeN - +----------+ - | ValN | - +----------+ -``` -The keys and values are encoded as standalone binaries, so the addresses in -`KeyI` (say) are relative only to the `KeyI` binary. - -### Initialization - -When a Sophia contract is called the calldata should be a pair of a function -hash and a tuple of arguments, encoded as a binary as described above -The value should be a pair of a function hash and a tuple of arguments -For instance, to call the function `foo` (assuming the function -hash 12345) with arguments `1` and `"bar"`, the calldata should be -(the binary encoding of) -``` - (12345, (1, "bar")) -``` -Before the contract starts executing the first word of the encoded calldata -(i.e. the calldata value) is pushed on the stack and the rest of the calldata -heap is written to memory. The result is that the Sophia contract starts with -the value of the calldata on top of the stack. - -If the contract state has been initialized it is stored on the heap and a -pointer to it is written to address 0. If the contract state has not been -initialized, for instance, when running the `init` function, 0 is written to -address 0. Note that address 0 contains a *pointer* to the value of the state, -not the value itself. - -The compiler is responsible for generating the appropriate dispatch code, -looking at the calldata and calling the correct function. - -### Return - -When returning from a contract call (using the `RETURN` instruction) the -type information from the meta data is used to encode the return value. -The VM reads the return value from the heap and returns it to the caller, -and reads the updated contract state using the state pointer at address 0. -A contract can write 0 to the state pointer to indicate that the state -did not change. - -### Storing the contract state - -The contract state is stored in the *store* as a binary heap whose first word -is the value (with maps stored as their identifiers) under key `0x00`. -The type of the state is stored as an encoded type representation under key -`0x01` (***subject to change: contract state type to be stored in contract -metadata***). The list of maps in the contract state is stored under key `0x02` -as a sequence of 256-bit map identifiers. For each map there are mappings -(where `[X]` denotes a single 256-bit word): -``` - [MapId] => [RealId] [RefCount] [Size] Types - [RealId] Key => Val -``` -`Types` is the binary encoding of the tuple `(KeyType, ValType)` of type -representations for the key and value types of the map. `Key` and `Val` are -stand-alone heap encodings with map identifiers for maps (although for keys -there are no maps). The `RealId` field is an indirection to allow in-place -updates of maps and the `RefCount` field is used to track the number of -occurrences of a map in other maps for the purpose of garbage collection. - -The `init` function of a contract should return a pair of the state type -representation and the initial state, which are written to the store by the VM. -Note that the Sophia code for `init` only returns the initial state value--the -compiler is responsible for adding the type representation. - -### Remote contract calls - -The `CALL` instruction for calling another contract works differently for -Sophia contracts than in the EVM. It expects on the stack (top to bottom): -- `Gas` - the amount of gas to allocate to the call -- `Address` - the address of the contract to call (or 0 for primops) -- `Amount` - the amount of tokens to transfer with the call -- `Calldata` - the calldata value (pair of function hash and arguments) -- `TypeHash` - the function hash of primops that have dynamic types - (e.g., oracles). Otherwise unused. -- `_` - unused (offset to write return value in the EVM) -- `_` - unused (return value size in the EVM) - -The calldata is read from the heap guided by the calldata type and passed to -the called contract. Before the call is made gas is charged for the size of the -expanded calldata (e.g. maps have to be made explicit when passed between -contracts). When the call returns the return value is pushed on top of the -stack, and potential heap objects for the return value written to the top of -the heap. The return type from the contracts meta data is used when writing it - to the heap. Since maps are handled outside the heap, the caller explicitly -pays gas for handling maps in the return value. - -### Delegation signature -Some chain operations (`Oracle.` and `AENS.`) has an optional -delegation signature. This is typically used when a user/accounts would like to -allow a contract to act on it's behalf. The exact data to be signed varies for the -different operations, but in *all* cases you should prepend the signature data with -the `network_id` (`ae_mainnet` for the Aeternity mainnet, etc.). diff --git a/docs/sophia.md b/docs/sophia.md index f75f52e..bd9cfbc 100644 --- a/docs/sophia.md +++ b/docs/sophia.md @@ -1061,34 +1061,4 @@ contract FundMe = spend({recipient = to, amount = state.contributions[to]}) put(state{ contributions @ c = Map.delete(to, c) }) -``` - -## The lifetime of a contract - -### Killing a contract - -There is no selfdestruct instruction in the aevm as in the Ethereum -Virtual Machine instead there is a disable transaction which the -creator of a contract can issue. When a contract is disabled no new -contract can call the old contract. - -When a contract is posted to the chain all references to other -contracts are checked and a reference counter in each contract is -increased. You can only post a contract to the chain if all the -contracts referred to are enabled. - -When a contract is disabled all other contracts it refer to get their -reference count decreased. - -If a contract is disabled and its reference count is zero a miner can -choose to garbage collect the contract. - -The reference count of a contract is handled as the account balance -and kept in the state tree of the miner and the merkle hash is -included in the state hash in each block just as with balances. - -The transaction for creating a contract has an extra fee called -deposit which has to be an even number. The disable transaction is -free but the miner and the creator get half of the deposit fee each at -contract disable thus encouraging creators to disable their contracts -and miners to pick disable transactions. +``` \ No newline at end of file