-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Contract API support for generating asynchronous transactions #175
Comments
Existing StubsAt the moment we have a stub from several months ago which defines this intrinsic in the wasm-vm: int send(void *tx_buffer, int tx_buffer_size); It seems that the idea was to serialize a whole transaction into the proper packed form and then pass it to the native code.
CONS:
Managed Transaction Alternativealternatively, if we make a slightly more complex api. We may be able to simplify what have to implement in the more restrictive wasm-vm environment typedef uint32_t TransactionHandle;
typedef uint64_t FuncName;
// create a transaction and auto-determine refBlockPrefix, refBlockNum and Expiration
TransactionHandle transaction_create(AccountName *scopes, int scope_count);
// add a message to the pending transaction
void transaction_add_message(TransactionHandle trx, AccountName code, FuncName type, PermissionName* permissions, int permission_count, void* data, int data_size);
// publish transaction (defaults to async, but can be sync)
void transaction_send(TransactionHandle trx, int immediate = 0); PROS:
CONS:
Other thoughts:in the above API, // add a scope to the pending transaction
void transaction_add_scope(TransactionHandle trx, AccountName scope); |
A middle ground is to remove the handle all together and only allow one "under construction transaction". There is a security vulnerability in the second approach that allows someone to allocate unbounded memory (almost) by looping over transaction_create or transaction_add_message. We must be very careful regarding any API that allocates resources. I think we can support both APIs. The first API is maximally flexible, the second one may have edge cases that are not predictable. |
I am comfortable with the single transaction mode. With the API that stands, I think its reasonable to limit the number of pending transactions to some small number and the "total serialized size" to some reasonable amount. Each call to
I would say that is "cheap at twice the price" but in this instance, pushing enough code into the wasm-vm to serialize None of the data structures managed by the alternative API are flexible from the point-of-view of a contract. The contents of I would say that interface is more fragile because it needs to be compiled with an awareness of the block-level "envelope" types which are only indirectly accessed by other contract facing APIs. For instance, we have abstracted access to |
after further review and beginning to implement, I would like to amend my proposal as follows:
There result is the following proposed C API: typedef uint32_t TransactionHandle;
#define InvalidTransactionHandle (0xFFFFFFFFUL)
#define SendInline (1)
#define SendDeferred (0)
TransactionHandle transactionCreate();
void transactionAddScope(TransactionHandle trx, AccountName scope, int readOnly = 0);
void transactionSetMessageDestination(TransactionHandle trx, AccountName code, FuncName type);
void transactionAddMessagePermission(TransactionHandle trx, AccountName account, PermissionName permission);
void transactionPushMessage(TransactionHandle trx, void* data, int size);
void transactionResetMessage(TransactionHandle trx);
void transactionSend(TransactionHandle trx, int mode = SendDeferred);
void transactionDrop(TransactionHandle trx); I am still working on the C++ api, but it, at least, adds type safety to the message payload. It will probably also provide an easier avenue for constructing transactions in a more declarative way. |
The point of a transaction is to enable multiple messages that depend on each-other to be applied atomically. I think that we should not use the "current" lack of malloc as an excuse to assume that a dev couldn't implement it. In fact, it is being implemented (in progress) right now. So I think we can assume up to N pending trx with up to M pending messages within each trx and a maximum temporary memory allocation of 64KB. I also like using inline (for in same transaction) and deferred to imply executed at block producers discretion. |
I think you misunderstand the concern with malloc et al. These transaction can have multiple messages, scopes and permissions. They are fully featured. this is valid for creating a transaction with 3 messages (albeit I skipped things like setting permissions etc); TransactionHandle trx = transactionCreate();
transactionPushMessage(trx, ...);
transactionPushMessage(trx, ...);
transactionPushMessage(trx, ...);
transactionSend(trx, ...); The question is who manages the variably sized temporaries while the transaction is in construction. The contract or the system. For now, the contract ecosystem is not very supportive of contracts managing temporaries because these don't lend themselves well to being WebAssembly locals. The usual suspects for managing variably sized things are not supported yet (heap allocation, stack allocation). If we had a system that accepted Sure we will eventually have a full ecosystem but, for now, this API is more consistent with the database and message APIs which abstract native types behind functions and, in my opinion, safer than the alternative of passing pointers and promises that the pointer is a valid array of the size the caller claims. |
This looks reasonable to me. Just keep in mind that there is function call overhead with your API that doesn't exist with other. At this point something that works good enough for EOS Dawn 1.0 is all that is necessary. |
As I get deeper into this, I think we may want to make some large changes to this system post EOS Dawn 1.0. Here are my thoughts:
|
After call with wanderingbort here is the conclusion:
Priority:
|
first swipe at processing thereof, need tests badly ref EOSIO#175
… for recursion and total TX time ref EOSIO#175
…mpty transaction failure ref EOSIO#175
exposed many bugs in the contract code and producer fixed what I found ref EOSIO#175
…ucers can vote on them ref EOSIO#175
ok, reflecting the comments from @bytemaster and our call the "final" API for this issue/PR is: TransactionHandle transactionCreate();
void transactionRequireScope(TransactionHandle trx, AccountName scope, int readOnly = 0);
void transactionAddMessage(TransactionHandle trx, MessageHandle msg);
void transactionSend(TransactionHandle trx);
void transactionDrop(TransactionHandle trx);
MessageHandle messageCreate(AccountName code, FuncName type, void const* data, int size);
void messageRequirePermission(MessageHandle msg, AccountName account, PermissionName permission);
void messageSend(MessageHandle msg);
void messageDrop(MessageHandle msg); for c++ there are wrappers manage handles for you and expose type same payloads for messages. test contractThere is a simple "proxy" contract as part of the tests. It runs in the "Slow tests". This allows you to install code on one account (the proxy) and set another account (the destination) as the "owner". Any transfer of EOS or currency will be relayed to the "owner" automatically in a deferred transaction. This couldn't be done conveniently with inline messages because it would require that the original sender of the transaction know the final "owner" account and list them in the The owner isn't private persay, but requiring a payer to inspect the contract state is silly. This could be extended to pay dividends of any eos or currency trasfer to a set of owners in proportion to their "shares" but that is left as an exercise to the reader this contract is not meant to be safe or really representative It is merely an example of a contract producing a deferred transaction because inline messaging was insufficient. At the very least, it should probably enforce that only the owner can set a different owner 😄 other notesMany of the limits of the current system are driven by the producer voting. For now they default to:
For now there is a cludge for permissioning until I or @bytemaster address #113 |
…ally even though it really should. ref EOSIO#175
closed by #389 |
WRT #175 (comment)
I believe that 'immediate' fits better than 'inline', as 'inline' implies that the line of code calling that action is replaced by the action code. Immediate is at least semantically unambiguous in the sense of how long it takes to return a result, with the only ambiguity being when the action is scheduled. 'Inline' implies it is scheduled at the moment of its call which is unambiguously wrong. Also, the official docs probably also need an update as they say
If the actions are executed sequentially, they are neither a part of the calling action nor nested transactions. |
# This is the 1st commit message: various improvements # This is the commit message #2: new hash # This is the commit message #3: fix for script path # This is the commit message #4: fixes # This is the commit message #5: fixes # This is the commit message #6: fixes # This is the commit message #7: fixes # This is the commit message #8: fixes # This is the commit message #9: fixes # This is the commit message #10: fixes # This is the commit message #11: fixes # This is the commit message #12: fixes # This is the commit message #13: fixes # This is the commit message #14: fixes # This is the commit message #15: fixes # This is the commit message #16: fixes # This is the commit message #17: fixes # This is the commit message #18: fixes # This is the commit message #19: fixes # This is the commit message #20: fixes # This is the commit message #21: fixes # This is the commit message #22: fixes # This is the commit message #23: fixes # This is the commit message #24: fixes # This is the commit message #25: fixes # This is the commit message #26: testing # This is the commit message #27: testing # This is the commit message #28: testing # This is the commit message #29: testing # This is the commit message #30: testing # This is the commit message #31: testing # This is the commit message #32: testing # This is the commit message #33: testing # This is the commit message #34: testing # This is the commit message #35: testing # This is the commit message #36: testing # This is the commit message #37: testing # This is the commit message #38: testing # This is the commit message #39: testing # This is the commit message #40: testing # This is the commit message #41: testing # This is the commit message #42: testing # This is the commit message #43: testing # This is the commit message #44: fixes # This is the commit message #45: fixes # This is the commit message #46: fixes # This is the commit message #47: fixes # This is the commit message #48: fixes # This is the commit message #49: fixes # This is the commit message #50: fixes # This is the commit message #51: fixes # This is the commit message #52: fixes # This is the commit message #53: fixes # This is the commit message #54: fixes # This is the commit message #55: fixes # This is the commit message #56: fixes # This is the commit message #57: fixes # This is the commit message #58: fixes # This is the commit message #59: fixes # This is the commit message #60: fixes # This is the commit message #61: fixes # This is the commit message #62: fixes # This is the commit message #63: fixes # This is the commit message #64: fixes # This is the commit message #65: fixes # This is the commit message #66: fixes # This is the commit message #67: fixes # This is the commit message #68: fixes # This is the commit message #69: fixes # This is the commit message #70: fixes # This is the commit message #71: fixes # This is the commit message #72: fixes # This is the commit message #73: fixes # This is the commit message #74: fixes # This is the commit message #75: fixes # This is the commit message #76: fixes # This is the commit message #77: fixes # This is the commit message #78: fixes # This is the commit message #79: more testing # This is the commit message #80: testing # This is the commit message #81: fixes # This is the commit message #82: fixes # This is the commit message #83: fixes # This is the commit message #84: fixes # This is the commit message #85: fixes # This is the commit message #86: fixes # This is the commit message #87: fixes # This is the commit message #88: fixes # This is the commit message #89: fixes # This is the commit message #90: fixes # This is the commit message #91: fixes # This is the commit message #92: fixes # This is the commit message #93: propagate-environment for buildkite-agent # This is the commit message #94: propagate-environment for buildkite-agent # This is the commit message #95: propagate-environment for buildkite-agent # This is the commit message #96: propagate-environment for buildkite-agent # This is the commit message #97: fixes # This is the commit message #98: fixes # This is the commit message #99: fixes # This is the commit message #100: fixes # This is the commit message #101: fixes # This is the commit message #102: fixes # This is the commit message #103: fixes # This is the commit message #104: fixes # This is the commit message #105: fixes # This is the commit message #106: fixes # This is the commit message #107: fixes # This is the commit message #108: fixes # This is the commit message #109: fixes # This is the commit message #110: fixes # This is the commit message #111: fixes # This is the commit message #112: fixes # This is the commit message #113: fixes # This is the commit message #114: fixes # This is the commit message #115: fixes # This is the commit message #116: fixes # This is the commit message #117: fixes # This is the commit message #118: fixes # This is the commit message #119: fixes # This is the commit message #120: fixes # This is the commit message #121: fixes # This is the commit message #122: fixes # This is the commit message #123: fixes # This is the commit message #124: fixes # This is the commit message #125: fixes # This is the commit message #126: fixes # This is the commit message #127: fixes # This is the commit message #128: fixes # This is the commit message #129: fixes # This is the commit message #130: fixes # This is the commit message #131: fixes # This is the commit message #132: fixes # This is the commit message #133: fixes # This is the commit message #134: fixes # This is the commit message #135: fixes # This is the commit message #136: fixes # This is the commit message #137: fixes # This is the commit message #138: fixes # This is the commit message #139: fixes # This is the commit message #140: fixes # This is the commit message #141: fixes # This is the commit message #142: fixes # This is the commit message #143: fixes # This is the commit message #144: fixes # This is the commit message #145: fixes # This is the commit message #146: fixes # This is the commit message #147: fixes # This is the commit message #148: fixes # This is the commit message #149: fixes # This is the commit message #150: fixes # This is the commit message #151: fixes # This is the commit message #152: fixes # This is the commit message #153: testing # This is the commit message #154: fixes # This is the commit message #155: fixes # This is the commit message #156: fixes # This is the commit message #157: fixes # This is the commit message #158: fixes # This is the commit message #159: fixes # This is the commit message #160: fixes # This is the commit message #161: fixes # This is the commit message #162: fixes # This is the commit message #163: fixes # This is the commit message #164: fixes # This is the commit message #165: fixes # This is the commit message #166: fixes # This is the commit message #167: fixes # This is the commit message #168: fixes # This is the commit message #169: fixes # This is the commit message #170: fixes # This is the commit message #171: fixes # This is the commit message #172: fixes # This is the commit message #173: fixes # This is the commit message #174: fixes # This is the commit message #175: fixes # This is the commit message #176: fixes # This is the commit message #177: fixes # This is the commit message #178: fixes # This is the commit message #179: fixes # This is the commit message #180: fixes # This is the commit message #181: fixes # This is the commit message #182: fixes # This is the commit message #183: fixes # This is the commit message #184: fixes # This is the commit message #185: fixes # This is the commit message #186: fixes
Related to #174
This task is for implementation of the contract API and related support for producing
GeneratedTransaction
for asynchronous calls to other contract methods.The text was updated successfully, but these errors were encountered: