How does one account send native coins to another account? Just using call? Is there a "receivable" function on the other end? Is there a way to transfer a balance without a call, i.e., a "simple send" tx type? (probably not, it doesn't make sense in the context of AA)
How do we pass input into a called function? Do we only allow calling a single entrypoint function? Do we use argc/argv or stick with using IO syscalls like now.
How do we return a value back from a call? Do we want to support this? Add an opcode or two?
Do we consume all remaining gas on failure?
Host-side
Encompasses everything the node (i.e., go-spacemesh) needs to implement.
Transactions
This design is maximally "abstracted," i.e., it puts as little logic as possible in the host and as much as possible in the VM.
There are only two transaction types: self spawn and wallet call.
Type 1: Self spawn
Self spawn allows a funded but unspawned wallet account to be spawned, same as in the existing VM. The transaction specifies the principal address, template address, and immutable state (init params). The wallet template has a self_spawn() method. The host passes the entire tx into this method. The method can either fail, or else internally spawn the template. The spawned wallet program address must be the hash of the template address and the immutable state.
Everything else is a call into a method in a spawned wallet program. We use the term "wallet" loosely, and we don't cleanly differentiate between wallet programs and non-wallet programs. Effectively a wallet program is any program that implements the "spend" and "proxy" methods described here (you can think of "wallet" like a Rust trait; a template may implement many traits, and a particular wallet may implement a subset of these methods, or additional convenience methods). Here are some examples of functionality wallet apps will likely provide:
Send
To send native coins from their wallet, the user generates a tx with their wallet program as principal. The tx is passed to the "spend" method on the wallet program, which either effectuates a send or fails.
To use a wallet's funds to pay gas for a call to another program, the user again generates a tx with their wallet program as principal. The tx is passed to the "proxy" method on the wallet program, which either effectuates the call to another program, or fails.
To deploy a new template, the user passes the template code to the wallet program, which uses a VM opcode to deploy a new template. The deploy opcode returns the newly-deployed template address, which is calculated as the hash of the template code. The deploy opcode fails if there's already a template deployed to this address. There's no verification of the template code at deploy time. The deploy opcode charges gas based on the size of the code.
To spawn a program from an existing template, the user passes the template address and immutable state (init vars) to the wallet program, which uses a VM opcode to spawn the program. The spawn opcode returns the newly-spawned program address, which is calculated as the hash of the template address, the principal address, and the nonce. The spawn opcode fails if there's already a program spawned to this address, or if the template init code fails to run on the input immutable state. The spawn opcode charges gas based on the template init code execution, i.e., same as a cross-contract call.
A stub is simply an account that has received funds but hasn't been spawned yet.
Templates
A template contains only code. Funds sent to a template account are effectively burned and cannot be moved. (Note that we cannot prevent funds from being sent to a template address before it's deployed, but once we know an account is a template we can prevent additional funds from being sent there.)
Programs
A program account contains a balance, a nonce, a state tree, and a link to an associated template address.
Questions
We need to finalize how wallets handle nonces. Note that the nonce is not fully abstracted into the VM since Spacemesh miners need to be able to read it for tx ordering.
VM-side
call
? Is there a "receivable" function on the other end? Is there a way to transfer a balance without a call, i.e., a "simple send" tx type? (probably not, it doesn't make sense in the context of AA)Host-side
Encompasses everything the node (i.e., go-spacemesh) needs to implement.
Transactions
This design is maximally "abstracted," i.e., it puts as little logic as possible in the host and as much as possible in the VM.
There are only two transaction types: self spawn and wallet call.
Type 1: Self spawn
Self spawn allows a funded but unspawned wallet account to be spawned, same as in the existing VM. The transaction specifies the principal address, template address, and immutable state (init params). The wallet template has a self_spawn() method. The host passes the entire tx into this method. The method can either fail, or else internally spawn the template. The spawned wallet program address must be the hash of the template address and the immutable state.
Type 2: Wallet call
Everything else is a call into a method in a spawned wallet program. We use the term "wallet" loosely, and we don't cleanly differentiate between wallet programs and non-wallet programs. Effectively a wallet program is any program that implements the "spend" and "proxy" methods described here (you can think of "wallet" like a Rust trait; a template may implement many traits, and a particular wallet may implement a subset of these methods, or additional convenience methods). Here are some examples of functionality wallet apps will likely provide:
Send
To send native coins from their wallet, the user generates a tx with their wallet program as principal. The tx is passed to the "spend" method on the wallet program, which either effectuates a send or fails.
Call/proxy
To use a wallet's funds to pay gas for a call to another program, the user again generates a tx with their wallet program as principal. The tx is passed to the "proxy" method on the wallet program, which either effectuates the call to another program, or fails.
Deploy
To deploy a new template, the user passes the template code to the wallet program, which uses a VM opcode to deploy a new template. The deploy opcode returns the newly-deployed template address, which is calculated as the hash of the template code. The deploy opcode fails if there's already a template deployed to this address. There's no verification of the template code at deploy time. The deploy opcode charges gas based on the size of the code.
Spawn
To spawn a program from an existing template, the user passes the template address and immutable state (init vars) to the wallet program, which uses a VM opcode to spawn the program. The spawn opcode returns the newly-spawned program address, which is calculated as the hash of the template address, the principal address, and the nonce. The spawn opcode fails if there's already a program spawned to this address, or if the template init code fails to run on the input immutable state. The spawn opcode charges gas based on the template init code execution, i.e., same as a cross-contract call.
Accounts
There are three kinds of accounts.
Stubs
A stub is simply an account that has received funds but hasn't been spawned yet.
Templates
A template contains only code. Funds sent to a template account are effectively burned and cannot be moved. (Note that we cannot prevent funds from being sent to a template address before it's deployed, but once we know an account is a template we can prevent additional funds from being sent there.)
Programs
A program account contains a balance, a nonce, a state tree, and a link to an associated template address.
Questions