Skip to content
This repository has been archived by the owner on Dec 26, 2023. It is now read-only.

AA Transactions & SVM Integration #53

Closed
YaronWittenstein opened this issue Jul 18, 2021 · 6 comments
Closed

AA Transactions & SVM Integration #53

YaronWittenstein opened this issue Jul 18, 2021 · 6 comments
Assignees
Labels
svm SMIPs related to SVM

Comments

@YaronWittenstein
Copy link

YaronWittenstein commented Jul 18, 2021

Overview

This SMIP will outline the required changes to the platform Transactions as a result of shifting towards the new Account Unification (#49) model and SVM Integration.

Additionally, the upcoming integration of go-spacemesh with SVM will require significant changes for clients as well.
Existing clients such as smapp and Process Explorer will have to adapt accordingly.

Goals and motivation

The motivation for this SMIP is to streamline the integration process between go-spacemesh and
SVM. Getting everyone up to speed with the same terminology and agreeing on the way things will work
is crucial.

In the new Account Unification (#49) model each Transaction will essentially be a Smart-Contract transaction,
or SVM transaction if to be more precise. Even simple coins transactions will be implemented as a Smart-Contract.

In SVM there is a distinction between deploying a Smart-Contract spec and creating instances of it.
A Smart-Contract specification is named a Template and each live instance is called an Account.

Each Account will have an Address and a balance and Template Address it was spawned from.
It will contain more internals which are out of scope for this document.

There are in total 3 types of Transactions SVM v0.3:

  • Deploy - Deploying Templates.
  • Spawn - Spawning Accounts out of deployed Templates.
  • Call - Calling an existing Account.

This SMIP will detail the fields that each Transaction will consist of without getting into low-level encoding.

High-level design

Each binary (over-the-wire) Transaction will consist of two main parts:

  • Envelope - A Transaction agnostic content.
  • Message - A Transaction specific content.

Each Message will be accompanied by the Envelope to form together a complete binary Transaction.

In addition to the explicit data sent over-the-wire, there will be implicit fields inferred from it.
One such example is the Transaction Id. For the context of this document, we won't regard these implied fields as part of the Transaction.

Adding to a binary Transaction, there is the Execution Context (or alternatively the Transaction Context or simply Context). The Context structure will contain additional data (alongside the Transaction) to be used by SVM when executing a Transaction. Properties such as Layer or Block Number and the State Root Hash will be part of it.
It'll be probably useful to attach implied properties such as Transaction Id as well to sit under the Context.

When SVM will be given a Transaction to execute it'll receive both the Transaction data and its attached Context.

Proposed implementation

Since SVM is implemented in Rust and go-spacemesh in Golang, it's of key importance to make life easier as much
as possible when designing the integration.

In order to make the two components talk, they will have to abide the FFI rules.
Each successful SVM CI will emit os-specific (macOS/Linux/Windows) binaries.

SVM FFI layer will be wrapped by a project named go-svm, serving as the bridge between Golang and Rust.
Any cGo related code will be handled by it. It will expose pure Golang API and mask any FFI related code to the external world.
The go-spacemesh will depend on go-svm and know nothing about its internals.

Generally, each call to go-svm for the sake of validation or execution will be equipped with:

1. Envelope

The parsed Envelope as a Golang struct.

Peeling off the binary Envelope out of a binary Transaction is the responsibility of the go-spacemesh.

2. Message

The binary Message is what's left after peeling-off the Envelope out of a binary Transaction.
This data is opaque to go-spacemesh and it will be passed as it's forward to the go-svm.

3. Context

The Context will be passed as a Golang struct into go-svm.
It will contain inferred data from the binary Transaction (e.g Transaction Id) and execution related data (e.g layer / State Root Hash).

Transactions Fields

Envelope

  • version - For versioning (to ease introducing new changes in the future).
  • type - The Transaction type (Deploy / Spawn / Call)
  • principal - The Address of the Account paying for the Gas.
  • amount - For funding.
  • tx_nonce - For the tx nonce.
  • gas_limit - Maximum units of Gas to be paid.
  • gas_fee - Fee per Unit of Gas.

The exact Encoding of the Envelope will be decided by the go-spacemesh team.
It can be XDR or any other encoding. The go-svm expects to receive an already parsed Envelopes
in the form of a Golang struct.

Message

Deploy

The Deploy Message will be generated by the Template compiler.
Right now it'll be using the SVM SDK, but in the future there might be more ways to achieve that.


 Important: There are no assumptions regarding the order of the Sections.

+----------------+
|                |
|  Code Section  |
|                |
+----------------+
|                |
| Data Section   |
|                |
+----------------+
|                |
| Ctors Section  |
|                |
+----------------+
|                |
| Header Section | (Optional)
|                |
+----------------+
|                |
| Schema Section | (Optional)
|                |
+----------------+
|                |
|  API Section   | (Optional)
|                |
+----------------+
|                |
| Deploy Section | (Optional, will be derived from the `Transaction Envelope` and `Transaction Context`)
|                |
+----------------+

Spawn

Each Spawn Message contain the following fields:

  • template (Template Address) - The Template we'll spawn an Account from.
  • name (String) - The name of the Account (optional).
  • ctor (String) - The constructor identifier to execute.
  • calldata (Blob) - The input for the constructor to run.
+-----------+-------------+----------------+
|           |             |                |
|  Version  |  Template   |      Name      |
|   (u16)   |  (Address)  |    (String)    |
|           |             |                |
+-----------+-------------+----------------+
|           |                              |
|   Ctor    |          CallData            |
|  (String) |           (Blob)             |
|           |                              |
+-----------+------------------------------+

Call

  • target (Account Address) - The Address of the Account which we're calling.
  • function (String) - The function`s identifier to execute.
  • verifydata (Blob) - The input for verify. See the Account Unification for more details.
  • calldata (Blob) - The input for the the function to run.
+-----------+-------------+----------------+
|           |             |                |
|  Version  |   Target    |      Name      |
|   (u16)   |  (Address)  |    (String)    |
|           |             |                |
+-----------+-------------+----------------+
|           |             |                |
|  Function | VerifyData  |    CallData    |
| (String)  |   (Blob)    |     (Blob)     |
|           |             |                |
+-----------+-------------+----------------+

The Encoding of each Call Message will be implemented by SVM which will provide a svm_codec.wasm.
Each successful SVM CI build will emit under its Artifacts the svm_codec.wasm.

Dependencies and interactions

  • SVM - The Transaction executor.
  • go-svm - The glue between go-spacemesh to SVM binaries.
  • go-spacemesh - Communicates directly only against go-svm.

Stakeholders and reviewers

@YaronWittenstein
@neysofu
@noamnelke
@sudachen
@lrettig
@avive

@YaronWittenstein YaronWittenstein self-assigned this Jul 18, 2021
@YaronWittenstein YaronWittenstein changed the title AA Transactions & SVM Integration AA Transactions & SVM Integration [WIP] Jul 18, 2021
@YaronWittenstein YaronWittenstein added the svm SMIPs related to SVM label Jul 18, 2021
@avive
Copy link
Contributor

avive commented Jul 19, 2021

I think it is important to add some design regarding signatures to the smip that answers these questions:

  1. Where is the signature in the transaction field?
  2. What transaction fields or sections are signed?
  3. Clarify how signing works - it must be sign on a hash of payload, not a payload so we can support ledger and other hardware wallets signatures requirements.
  4. What signature formats are going to be supported for 0.3? I assume ED and ED++.
  5. How does the use of signature scheme affects the transaction field. For example, in ED++ signatures the public key is not part of the payload but in ED it is.
  6. Need to spec the signature verification algorithm which may not be trivial as it combined contextual information not in the tx payload. e.g. netId.

@tal-m
Copy link

tal-m commented Jul 19, 2021

@avive There's no specification for what is signed at this level. The signatures are decoded and verified in the verify method of the account --- this can vary from account to account.

I think there should be a separate SMIP (maybe SMIPs) for the specific account types we'll have at launch. Each account type specifies the answers to your questions (Except for q.4, which is common for all of them --- because raw signature verification must be supported in native code on the SVM side --- and possibly q.5 --- see below).

Q.5 actually is a bit tricky, and does relate to this SMIP. We have to keep in mind that sometimes decoding of the envelope is actually transaction-dependent. This is the case, for example, when we're doing public-key extraction. The encoded transaction in this case doesn't have the principal's address. Instead, the address is extracted from the signature.

We said we'd solve this by having an external "decoding" layer, that recognizes specific transaction types and "decodes" the principal address by running the PK extraction. If this decoding is done on the go side, as you suggest in this SMIP, there will be some duplication of code --- both the decoder (in go) and the verify function (in SVM) will need to run ED++ signature verification operations.

Alternatively, we can have the transaction decoding step also take place on the SVM side, which I think is a little cleaner in terms of software design. This would potentially allow us to encode/decode in more optimized ways in the future, and my guess is that it would be more efficient as well (since there's less context switching between go and SVM).

@lrettig
Copy link
Member

lrettig commented Jul 28, 2021

Transactions Fields
Envelope
version - For versioning (to ease introducing new changes in the future).

Is this "version" of the transaction object or SVM version? If the latter, maybe we could give this a more generic name such as "vm_type" (since it may not just be a version, it may indeed include both the name of the engine -- svm, evm, rollup-specific engine, whatever -- and the version)

type - The Transaction type (Deploy / Spawn / Call)
principal - The Address of the Account paying for the Gas.

paying for the gas and the source of funds for amount (if we include this)

amount(*) - For funding (see more information later under Questions/concerns).
gas_limit - Maximum units of Gas to be paid.
gas_fee - Fee per Unit of Gas.

gas limit and gas fee semantics here depend upon whether we go with an EIP-1559-like mechanism, which seems likely.

Call
target (Account Address) - The Address of the Account which we're calling.
function (String) - The function`s identifier to execute.

might want to explain how the identifier is calculated. in EVM it's a hash of the full function signature - I assume we want to do something similar?

@YaronWittenstein
Copy link
Author

Transactions Fields
Envelope
version - For versioning (to ease introducing new changes in the future).

Is this "version" of the transaction object or SVM version? If the latter, maybe we could give this a more generic name such as "vm_type" (since it may not just be a version, it may indeed include both the name of the engine -- svm, evm, rollup-specific engine, whatever -- and the version)

Versioning of the Transaction Object.

type - The Transaction type (Deploy / Spawn / Call)
principal - The Address of the Account paying for the Gas.

paying for the gas and the source of funds for amount (if we include this)

amount(*) - For funding (see more information later under Questions/concerns).
gas_limit - Maximum units of Gas to be paid.
gas_fee - Fee per Unit of Gas.

OK. I'm certain that the amount must be part of the Envelope.
We need to be able to tell its value without running SVM by just plain parsing of the Envelope.

gas limit and gas fee semantics here depend upon whether we go with an EIP-1559-like mechanism, which seems likely.

I'll read this EIP.

Call
target (Account Address) - The Address of the Account which we're calling.
function (String) - The function`s identifier to execute.

might want to explain how the identifier is calculated. in EVM it's a hash of the full function signature - I assume we want to do something similar?

I don't think we need to use any hashing because in Wasm there is no function overloading, the function name is a unique identifier. Also, the compiled Wasm (SVM SDK -> Wasm) will contain very short names for these functions in order to reduce the space of a transaction.

@YaronWittenstein YaronWittenstein changed the title AA Transactions & SVM Integration [WIP] AA Transactions & SVM Integration Aug 24, 2021
@avive
Copy link
Contributor

avive commented Sep 30, 2021

If all the Envelope fields are final then next step in this smipp should be providing the data type of each Envelope member and the Envelope binary codec. This will move us towards clients being able to create sm 0.3 transactions (and decode them for display to users) and explorers decoding them for display purposes.

@avive
Copy link
Contributor

avive commented Oct 4, 2021

Additional things that should be added to this smipp (or to a followup one) that we need in order implement 0.3 transactions:

  • Spec the data that clients need to provide for the Call fields for a simple coin transfer tx between accounts and a multi-sig transaction (I believe using the vault smart contract). These fields:
export interface Call {
    version: number;
    target: string;
    func_name: string;
    verifydata: Uint8Array;
    calldata: Uint8Array;
}
  • Spec the data that client need to provide to spawn a vault. These fields:
export interface Spawn {
    version: number;
    template: string;
    name: string;
    ctor_name: string;
    calldata: Uint8Array;
}

I understand that specing the fields for vault smart contract transaction (spawn and call) is not possible yet until the vault contract is designed but we should be able to spec these fields for a simple coin transaction.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
svm SMIPs related to SVM
Projects
None yet
Development

No branches or pull requests

5 participants