-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AIP-044: Third-party transaction execution #44
Comments
@jeff-aion Thank you for submitting. Since you already have the proposal, do you want to proceed this as a formal AIP? |
Changing the status to Discussion and assigned AIP number. |
Yesterday, we decided to add this to the scope of the next hard-fork. |
An Invokable transaction is encoded as a byte array as follows: The first byte is a version byte, which for now must be 0. The signature is calculated on the RLP encoded list of the other 5 fields, prepended with the version byte. The transaction hash is calculated as the blake2b hash of the entire encoded Invokable transaction. |
Title: Third-party transaction execution
Author: Jeff Disher
Type: Core
Status: Discussion
Creation Date: 2019-08-20
Contact information: [email protected]
Summary
This proposal describes a mechanism for paying to run a preserialized transaction, typically signed by another user, from within an already-running AVM transaction.
This allows for running a transaction as one user but paying for it as another.
The key idea here is that this is not known at the base protocol level: The entire system just treats this serialized transaction as generic data, except for the one API routine which accepts this input.
Additionally, a goal is to generalize this enough that it doesn't only solve third-party billing but can become a primitive within more complex idioms, yet to be considered. However, the billing problem is the key driving factor here.
Problem
In order for a user to submit a transaction to the blockchain, they must have an account balance to purchase energy.
This makes it impractical for a developer to expose native blockchain functionality within an application, as this would alienate the vast majority of their users.
If the developer could pay this fee on the user's behalf, the barrier to use is dramatically lowered.
Objectives
In order to generalize the approach, the scope of objectives has been slightly expanded:
Concerns Outside of Scope
Architectural Overview and Concepts
The flow we are expecting should work like this:
In this diagram, USER and OWNER are off-chain, standard accounts. TARGET and PROXY are on-chain contracts. Flow of execution to emulate "USER sends T to TARGET":
Blockchain.invokeTransaction()
routine, along with an energy limitTerminology we define to keep this proposal clear:
Specification Details
We propose the introduction of a new method on the Blockchain API class, in the AVM:
public static Result invokeTransaction(byte[] transactionPayload, long energyLimit)
This method operates similarly to the call() or create() methods, except that it takes a transactionPayload which is a serialized transaction, including signature. If the transactionPayload is a valid transaction, with correct nonce and signature, then it is executed as an internal transaction. The key difference, however, is that a normal internal transaction maintains the origin of its external transaction and uses the invoking contract address as its sender. In the case of this preserialized transaction, the original signer of the transaction appears as both of these.
Note that stack depth is still counted across this call, meaning this maximum depth before overflow is the only behavioural difference, within the contract, when compared to a normal external transaction.
Error cases thrown as IllegalArgumentException (note that such errors are analogous to "rejection" and do not increment the nonce):
Receiver-side perspective of the invocation, in terms of Blockchain behaviours (omitted methods are same as normal):
getCaller()
- the "sender" as written into the serialized transactiongetOrigin()
- the "sender" as written into the serialized transactiongetEnergyLimit()
- the limit specified by the callergetBlockTimestamp()
- the timestamp of the current block (where this is executed - not anything related to when it was signed)getBlockNumber()
- the block number of the current block (where this is executed - not anything related to when it was signed)call()
/create()
- generally the same as normal except that the maximum call depth is still reduced by one for every call in the current stackThe contents of this transaction are slightly different, as well:
To avoiding reinventing more than is required, the transaction will be serialized as an RLP-encoded list, much like standard transactions (only difference being which data elements are included in the list).
Note that contract creation is possible with this kind of transaction, but only AVM contracts can be deployed this way. Bytecode for a different virtual machine will just be interpreted as invalid data and will fail deployment.
This inner transaction is stored by its hash (hash including the signature), since there is no other mechanism which can be used for globally addressing it. The data returned for this transaction, when its receipt is requested, will have only basic data, including a reference to the external transaction where it was executed. In general, side-effects of an inner transaction are persisted much as a standard internal transaction.
Logical Flow and Examples
There are 2 prototypical examples of how this could be used:
Third-party billing ("try before you buy")
Delayed execution ("post-dated cheques")
Risks and Assumptions
We are assuming the following things about the user who is signing the transaction (not the developer who is paying for it):
Testing Considerations
Externals
The text was updated successfully, but these errors were encountered: