smapp
smapp copied to clipboard
Integrate new transactions structure: single-sig accounts
This issue contains bunches of questions in corresponding sections. Please indicate what time you are talking about: ASAP / Genesis / Post.
Rationale
This is an epic issue, that should be divided into smaller ones. But let's clarify all the details first.
The transaction structure and API have been changed due to support vaults. Within this issue we want to integrate these changes into Smapp and support:
- creation of single-sig accounts
- smeshing and getting rewards on such accounts
- sending SpendTransactions to other single-sig accounts
Links to related changes in API & Go-Spacemesh:
- https://github.com/spacemeshos/api/pull/164
- https://github.com/spacemeshos/api/pull/165
- https://github.com/spacemeshos/go-spacemesh/pull/3295
- https://github.com/spacemeshos/go-spacemesh/pull/3229
Details
Concepts
- Principle address — is the address of the single-sig account
- Principle address should be used as coinbase for smeshing then.
- To calculate a principle address we need to encode (?) the template address and arguments
- In this case, argument is PublicKey,
- The key pair may be generated/imported by Smapp and stored in the wallet file,
- To send any transactions to the network User have to sign these transactions with the corresponding private key
Keys
So we will have two kinds of addresses stored in the wallet file:
- Keys — key-pairs used in spawning accounts and signing transactions
They still should be generated from mnemonics, and probable should use HD wallet standard.
At the moment we use
ed25519wasm-implementation, which implements deriving by index only (or mb I miss something). - Vaults — list of principal addresses, that the User is interested in. Basically, this is the list of Principal addresses, which makes it easier to listen for updates only for particular addresses. In case the User lost his wallet file and recovers from mnemonics he has to import vaults using the same arguments or vault address. So basically not so user-friendly, but improving this user story is out of scope for this issue.
To make it a bit easier, we can pre-create one single-sig account by default (without spawning), as we're doing it now with the first derived key pair.
On the creation of subsequent single-sig accounts, the User will be asked to choose one of the existing keys or to generate a new one. If he wants to "recreate" the vault of another key, he has to reimport the keypair first.
He can reimport it just by creating new accounts (aka find needed derived index / HD path), importing a private key (not implemented).
Without owning a keypair User can reimport the vault only by its address.
QUESTIONS:
- Do we need an HD wallet?
Codec
Besides this, the new transaction structure uses scale codec.
That means that to read the transaction we need to decode a raw part of the transaction using schema related to a particular template address and method. Afterward, we can store decoded data in a persistent store on fs (like we're doing using AccountStateManager), show it, etc.
QUESTIONS
- Do we hard-code template addresses or do we have any open on-chain storage for it?
- Do we already have some service for encoding/decoding transactions (within such on-chain storage/service aside)? I remember something like that, but I can't find it.
- Or do we have to implement encoding/decoding in JS?
- Do we have any service with encoding schemas or something similar? Aka (I got tx with template address
0xbband method0x01, then I want to decode it, it will be cool to have something like this:const msgSchema = await Node.requestMessageSchema(0xbb, 0x01); const { recipient, amount } = decode(rawTx, msgSchema); - Meanwhile, we have to stick somehow Smapp's GUI to core message schemas. So, do we have some smart mechanism for that, or do we have just to hard-code template addresses?
I'd appreciate any help and ideas! 🙏 cc: @maparr @dshulyak @noamnelke @lrettig @oriya
Tasks
- [ ] Implementing of BECH32 addresses
- [x] @abergasov extracted related code into spacemeshos/address
- [x] @abergasov also helped me to wrap it into wasm: spacemeshos/address-wasm
- [ ] Integrate usage of
address-wasmlibrary in Smapp where needed
- [ ] Implement codec library
- [x] I've created spacemeshos/sm-codec library, which uses
address-wasmunder the hood - [ ] Test it well on the working network / longevity cluster
- [x] I've created spacemeshos/sm-codec library, which uses
- [ ] Integrate new API and related libraries into Smapp to migrate to the new tx structure without any regressions
A couple more questions regarding sending tx flow. As a Smapper I've run Smapp and have a pre-created single-sig account (or created it manually). Then I smesh and get some coins there... and I want to send a Tx to my friend:
- Do I need to explicitly sign and publish spawn tx? Or it should be automatically sent under the hood?
- If automatically, then does the Node take care of it or clients should take care?
Do we hard-code template addresses or do we have any open on-chain storage for it?
we don't have any storage. for genesis it makes sense to hard code them
Or do we have to implement encoding/decoding in JS?
yes, encoding and signing is done on the client
Do we have any service with encoding schemas or something similar?
we don't have such service and schemas. it probably will be introduced together with svm, but for now it is not important. i assumed that for genesis all schemas will be known to the client, so they can be hardcoded as well.
Do I need to explicitly sign and publish spawn tx? Or it should be automatically sent under the hood?
self-spawn needs to be applied to the chain before submitting any other transactions. it should be done explicitly by the client, i am not aware of any option to make it automatically somehow
Or do we have to implement encoding/decoding in JS?
yes, encoding and signing is done on the client
Do we have any service with encoding schemas or something similar?
we don't have such service and schemas. it probably will be introduced together with svm, but for now it is not important. i assumed that for genesis all schemas will be known to the client, so they can be hardcoded as well.
We previously discussed publishing a single Wasm codec that could be shared by SVM as well as by smapp and other downstream clients. I suppose this is up in the air at the moment, pending SVM design, CC @WilfredTA.
Do I need to explicitly sign and publish spawn tx? Or it should be automatically sent under the hood?
self-spawn needs to be applied to the chain before submitting any other transactions. it should be done explicitly by the client, i am not aware of any option to make it automatically somehow
Two notes:
- The spawn tx does not need to be published until the user wants to actually spend/move the funds. In particular, it does not need to be part of the smeshing setup. The user can safely accumulate funds (from coinbase txs, or from other sources) into their account, secure in the knowledge that they can spawn and spend those funds later (as long as they have the associated private key).
- It's theoretically possible to create a special, atomic "spawn-and-spend" tx that accomplishes both in a single tx (for an account that hasn't been spawned yet). Not sure what's the status of this on the VM/node side (CC @dshulyak @noamnelke). This can be done as two separate txs, but having an atomic tx type may result in slightly better UX/lower fees -- e.g., what happens if the spawn and spend txs are sent separately, around the same time, and the spawn doesn't make it into the block but the spend does?
We previously discussed publishing a single Wasm codec that could be shared by SVM as well as by smapp and other downstream clients ❤️ Do we have any estimation on it? @WilfredTA
So the basic user story:
- The user get some SMH on his not spawned yet single-sig account
- Then User explicitly sends a spawn transaction
- User waits until this tx will be on-chain: Meanwhile, Smapp has to detect, that the User already sent a spawn transaction and it has a pending status, so Smapp should not allow sending one more spawn transaction until this one fails.
- Then User can send a spend transaction
Correct?
3. Smapp has to detect, that the User already sent a spawn transaction and it has a pending status, so Smapp should not allow sending one more spawn transaction until this one fails.
Ideally spawn transactions should be idempotent, so that sending another one would have no effect and do no harm. (Nodes should drop them as duplicates.)
One more point: the "spawn" part should ideally be invisible to the user, i.e., from the frontend/UX/smapp perspective, the user should not need to create a "spawn" transaction separately from the first spend. When the user first tries to spend funds from the account, smapp should just automatically generate and send the spawn tx first.
I want to emphasize that smapp should wait for a spawn transaction to execute. Effectively wait for the result. Only after that point other transactions from the same principal will become parsable and won't be discarded by the api.
It's theoretically possible to create a special, atomic "spawn-and-spend" tx that accomplishes both in a single tx (for an account that hasn't been spawned yet). Not sure what's the status of this on the VM/node side
we don't have anything like that implemented
It's theoretically possible to create a special, atomic "spawn-and-spend" tx that accomplishes both in a single tx (for an account that hasn't been spawned yet). Not sure what's the status of this on the VM/node side
we don't have anything like that implemented
It can always be added as a new tx type later, and it's not critical (as long as the above UX is managed by smapp)