stellar-protocol
stellar-protocol copied to clipboard
New transaction flag proposal: Bump sequence on fail
In the current implementation of account sequence numbers when an account publishes a tx and it gets propagated to the network the accounts sequence number will be increased regardless of whether tx was successful or not. This behavior can be undesirable when working with pre signed transactions because when the accounts sequence number changes then a tx with the same operations and a new sequence number will have a different hash. Related issue. https://github.com/stellar/stellar-protocol/issues/51
If it was possible to explicitly mark that tx should not increase sequence if it fails then it would make Stellar smart contracts much more flexible, it would stop an observer from ruining the smart contract by bumping sequence and it would make it easier to reason about Stellar smart contracts.
The discussion that led to this issue is here https://github.com/stellar/stellar-protocol/issues/53 and while this this proposal is not as powerful as allowing sequence number to be changed to an arbitrary number it preserves the invariant that every tx is applied to the ledger at most once.
Unfortunate implication is that an observer can publish the same tx multiple times until the source account is depleted by tx fees. The proposed solution is keeping the smart contract at minimum deposit and whenever someone wants to run the smart contract they send some XLM to it as gas.
I like this idea, and I would reverse it: make it that it's an opt-in instead of an opt-out (ie: when not specified we keep the current behavior).
Going to implementation:
Where this gets a bit more complicated is that right now we do not have a flag at the transaction envelope layer - so we'll have to add this as an extension (using ext
and a new value for the value discriminant).
As we start to think about additions especially on the smart contract front, we can bundle those new fields in one go. I suspect we're only getting started on that front :)
And after writing this I am thinking maybe this is a property of the account and not of the transaction: in a smart contract context, maybe this is the behavior that we want for all transactions for that account.
The funding to run (aka gas) is a concern though if it cannot be done in an atomic fashion. Right now the only unit of atomicity is the set of operations within a transaction, so in theory this allows to DoS a contract by just front running transactions with old transactions (and in this case, just submitting them all the time) ; it also makes it harder to not propagate transactions like this across the network (right now we just don't flood them).
We may be able instead to punt the failure up, I think it can be thought of as the same problem than dealing with pre-signed transactions that don't meet the minimum fee requirement (an other transaction level failure). I think in BTC this is done by allowing a tx to pay for the fee for a different tx, in Stellar, this could just be done by nesting tx and have the outer tx pay for the fees missing from the inner tx (note this change is also a change on the envelope). The additional complexity may not be that bad and basically allows a parent transaction to perform any adjustment (through its own ops or transaction ordering) such that the child tx becomes valid. We would probably put the same type of limits on that tree that exists on the tx today (ie: limit on the number of operations) ; I am not sure about the full semantics yet but I imagine that we would require all tx to be valid to avoid replay.
I agree that it should be opt-in instead of opt-out. My bad for not being more explicit.
To make this functionality a part of the account is a good idea. Right now changeTrust operation can have different outcomes based on the auth_required flag. Therefore this philosophically fits in, however I will not have a strong opinion on implementation.
Theoretically there might be a smart contract that rely on both sequence bumping behaviors and then tx flag is more flexible, however such a smart contract is specific enough to be neglected. Also there is a workaround if account flag is implemented: Suppose there is a smart contract that does transactions T1, T2 and T3 in sequence. T1 and T3 have to succeed so they do not bump sequence if they fail. T2 is such that it has to be tried, but if it fails than sequence is bumped anyway. We can modify this smart contract so that the last operation of T1 is to unset the account flag. Increase the sequence number of T3 by one and make a new transaction T2' that has sequence between T2 and T3. The only operation of T2' is to set the account flag. Note that T2' cannot fail.
If we really want to start pushing the smart contract front then I suggest to clearly define the scope of what should be possible to accomplish with Stellar smart contracts. For example, we should be able to create oracles that have specific limited influence on other smart contracts, we should be able to create a smart contract for crowd funding, we should be able to implement different kinds of auctions, we should be able to make basic financial instruments like loans, bonds and futures. This could be the topic of a different issue.
I do not see how gas sending has problems if it is not atomic. Let us assume there is a smart contract that has two valid pre signed transactions T1 and T2 such that T1 is the transaction that will succeed if its operations are applied and it is the transaction that the person who pays for the gas wants to publish. T2 will be a transaction that will fail and is used to DoS the contract. I will now explain how I believe stellar consensus works so correct me if I am wrong:
- A sends gas (with excess to cover next 10 ledgers) to smart contract
- B repeatedly sends T2 to network
- only one instance of T2 per ledger close can get into the transaction set
- A sends T1 to network
- at some point in near future T1 will get into some transaction set
- if T1 is in a transaction set that T2 is not in then there is no problem
- if T1 and T2 are in the same transaction set then stellar core will try to apply them independently. given that T2 will fail and will not bump sequence T1 can still be applied even if it comes after T2 in transaction set
@Ratniex
If we really want to start pushing the smart contract front then I suggest to clearly define the scope of what should be possible to accomplish with Stellar smart contracts. For example, we should be able to...
I've been working on putting together a repository of smart contract implementations and have added some of your use cases. Please feel free to add some more or comment with clarifications!
https://github.com/zulucrypto/stellar-smart-contracts/issues
@Ratniex, are you up for reviving this with a draft CAP proposal?