-
Notifications
You must be signed in to change notification settings - Fork 118
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
TX 21 -- desired enhancement -- placing multiple orders from same address for same currency pair #270
Comments
Is there a way to lookup/compare the original offer values versus the ones in the cancellation? This would be a straightforward path to looking up the offer and marking it as a cancel - On the same token, if there are multiple offers with the same offer values and a cancel comes in , all of the offers with the same offer values would be cancelled. |
My initial thoughts on this are:
However, by adding an extra informational field on the cancel and update side of things we can thus nominate a specific sell offer to update/cancel. This extra informational field could for example be the last 8 bytes of the sell offer TXID to be updated which would push the packet size to 36 bytes - two packets for Class B or a single OP_RETURN output for Class C. This would then provide the per order update/cancellation process while supporting multiple sells per pair for an address. Thanks |
Also couple of notes from Skype chat:
Thanks |
There are a few other issues that were created in a context of "selecting" specific transactions. Using the transaction hash seems only reasonable and is very robust - length aside. Depending on how it's done, it might not be as bad as it seems: Cancel one:
(note: placing the action field at the very end is flawed imho) vs.
Cancel all:
*A new action value isn't ambiguous and seems appropriate, given that junk data might be mistaken for a transaction reference. Stuffing the reference with 111..11 is wasteful and feels wrong, because the inted is not to "cancel (a single) offer with txid 111..11" but something different. Updating specific orders - or queries such as "cancel all orders with currency pair x/y" - seems like a challenge though. Edit: actually.. it might also be an idea to stop thinking about how everything could be fit into a single transaction or action and start to use a very wide range of more specific update/delete/create operations. The transaction type field on it's own provides space for 65536 values - which makes me wonder: why bother with sub-actions at all? |
@marv-engine @dacoinminster comments please? |
My initial comments:
|
We had a meeting about this, and we decided:
|
There's a complication for identifying the sell order to cancel or update - I think it makes sense for it to be the value that was in the create or the most recent update tx21 message. @zathras-crypto @m21 @faizkhan00 @dacoinminster @achamely what do you think? |
Agree it should match the previous TX21 - not the current state of the order |
Agreed as well - the identity of the offer to act on should be the last tx21 to affect that address/currency-pair (or the original tx21) |
This still seems ambiguous to me. Eg Which one am I cancelling and/or updating when I send in the 'cancellation' values of 100 #n and 200 #y? If it's most recent or oldest etc, what if I want to change one of the other ones? I'm prevented from cancelling/updating all but one of the orders in current form it seems. It strikes me as remaining ambiguous. The same transaction (cancel/update with 100 #n and 200 #y values) has three different potential outcomes on the change to my balance depending on which is updated. I understand we can set orders of precedence but we have to also make this simple for end user. Could someone tl:dr; for me why we didn't want to reference the last 8 bytes of the tx hash, where we already have a unique sell offer identifier? We're talking about adding 16 bytes worth of fields in the proposed so it can't be tx space. 16 bytes to give #n and #y values to help us potentially locate the right offer Thanks |
PR #271 is ready for review and merge. |
Which sell offer identifier are you referring to? But I agree. And I also realized thanks to your post and contrary to my initial believe a full hash is not required, given that the address of the sender acts as additional identifier. This is imho especially relevant regarding the other discussions about selecting specific offers and so on. |
@zathras-crypto At the mtg yesterday I asked about doing something to/with the tx hash to get a shorter unique value (e.g. with the sender address) but no one offered this idea. I prefer explicitly using an identifier, rather than other attributes, to identify the sell offer or any other object. Can you explain how your idea produces a unique identifier? |
I believe the idea is to use parts of the (completely random) hash/txid of the transaction used to publish an offer. Due to the composition with the sender's address or a reference in general (e.g. for accepting offers) this should yield sufficient collision resistance. |
I'm fine with this route, except for one thing: we still have to write code On Fri, Oct 10, 2014 at 9:38 AM, dexX7 [email protected] wrote:
|
. . . I'd suggest that an update/cancel should affect the oldest matching On Fri, Oct 10, 2014 at 11:21 AM, J.R. Willett [email protected] wrote:
|
On an UI level the user could be notified about a collision before sending the update. On a protocol level I'd say: apply update/x to oldest first. In the worst case an update which actually doesn't update anything could be sent to get a "fresh" reference. |
What if no specific length such as 8 byte is defined at all and one would simply provide a sufficient long piece of hash to avoid conflicts? Say I have only one open order: this is unambigious even without any reference. In the case of two, I would likely get away with providing only one byte, etc. ... this would require publishing information about the acutal length, because a string null-terminator likely doens't work here. |
Ooooo. Interesting idea! So: 1 byte for the length of the shortened hash (however many bytes are needed If for some reason there is still a collision (due to a reorg or UI error), Sound good? Apologies to Marv for sending him on a wild goose chase . . . On Fri, Oct 10, 2014 at 11:46 AM, dexX7 [email protected] wrote:
|
In my opinion this sounds perfect. Hopefully this is what @zathras-crypto had in mind as well. :) |
Another idea - Because this identifier is address-specific, the user and wallet know what other sell orders (and identifiers) are active when the user is creating the new order. If we let the user enter an identifier for the new order, the wallet can check that it's unique among active orders for the address (and the currency id pair). If the wallet generates the identifier for the new order, it can use or hash the current timestamp as the id. If by some chance the id is not unique when the tx21 (New) is processed, then it's marked invalid. |
Not necessarily. But say this doesn't matter: what's the upside? |
Guys, IMO it's not necessary to force the customer to track down the original trade(s), ordering, blocks, TXIDs or anything of that nature. Consider the following scenario from the user's point-of-view here (orders are from the same address, for the same currency-pair all issued at the same effective unit price). These commands are issued by the user in question, in the following order: a) TRADE 50tokens for 5MSC Steps a, c, e put the tokens up for sale. Now, if all clear so far -- let me introduce the buyer(s) into the equation. |
@dexX7 what I meant was: Identifiers could be reused once a sell order to no longer active. The upside is that there's no ambiguity about identifying a sell order to be updated/cancelled. The identifier is unique for active sell orders for the address. |
@m21 one reason the seller wants to be specific about which order is updated/cancelled is that the protocol's matching algorithm chooses the oldest first if there are multiples that match at the same price. So, a seller wouldn't want to lose his place as the current oldest. |
Can you be specific please? |
@m21: what if I have several offers for the same currency pair, but on different price levels? Locating or targeting orders would be used to resolve ambiguousness (if wanted, needed). Providing a zero length reference could equal the intend to let some default logic handle the selection. @marv-engine: only the state of "inactive" offers is certain and actions are linked to transactions - which are fully identifiable right from the start, so providing another identifier seems sort of redundant. |
@dexX7 the application-provided timestamp, or user-entered N-byte string as an identifier is useful because it's a lot shorter than the tx hash, and it can be checked for collisions against a comparatively short list of the address' active orders before the tx is broadcast. Identifiers of past (inactive) offers aren't of interest and they can be ignored. The id could also be a serial number in 2 bytes - the wallet just adds 1 to the current highest active id. If 65k isn't enough, we could use 4 bytes to support 4 billion orders per address (and per currency pair, if we want). |
@dacoinminster The protocol defining the "effective price" as INT64 / INT64 gives us double the precision of a float to begin with. I did start a conversation on precision and limits with Marv (gotta find my notes), but there are pretty low limits we run into even with 128bits. Here's an example my my oderbook with 10-digit precision after the period: You can see that trading 1 Satoshi for 200 BTC (coins) is already impossible. UPDATE: the spec may not have an issue, if we stick with INT64 / INT64 JR, all -- I take that back. |
@dacoinminster -- spec may not have an issue with precision, if we stick with INT64 / INT64 JR, all -- I take that back. So no worries. |
I haven't been able to keep up with the latest direction of this thread, but I have a proposal of my own which I think eliminates a lot of the complexity. It provides a way to identify the sell order to be affected by an update or cancel, so multiple orders with the same currency pair and terms are treated separately. That's simpler than trying to figure out how to aggregate multiple tx21's into a single order. We can implement Update and Cancel as tx21 sub-actions or as new txtypes. I don't think it matters. Update/Cancel msg will include the following items to identify the target tx21:
MasterCore will confirm the correct seller (sender) address and txtype=21. The combination of these 5 items should make it highly unlikely that a re-org will cause the wrong tx21 to be affected. If the sender address and txtype in the specified tx aren't right, then the Update/Cancel is invalid. Update can:
Cancel can:
|
I assume you mean transaction position within block? There is no need for block time and strictly seen also no need for an address, because height + position is already unique. But in general: this is imperior to a selection via transaction hash, because block height and transaction position are mutable in the case of block reorganziations. It's worth to read the recent discussion - the trend is in favor of merging orders by price with commands such as |
A big disadvantage of using tx hash is its length. How often does a re-org Keeping the orders separate requires much simpler logic than trying to On Thursday, October 16, 2014, dexX7 [email protected] wrote:
Marv Schneider |
Regarding blocks: it's "often" the case that two miners find a new block at a somewhat similar time whereby only one is accepted by the network and the other is orphaned. An overview (which doesn't necessarily reflect all occurrences of such an event): https://blockchain.info/orphaned-blocks Given how Master Core is constructed, selecting orders by transaction hash piece or height + transaction position would probably be equally easy to implement. Edit: re: length: it should usually require less length of hash piece than height + position.
That's arguable. If it is indeed possible to select orders by price without introducing all kinds of edge cases, then it's simply "match oldest order first" and "subtract from newest order first" for a specific price level, see #270 (comment) for an example. |
@dexX7 , all (UPDATE is no longer in the picture = could be added later at its own block height if atomic REPRICE-RELIST command is needed, too confusing at this moment). |
Please not. There is no need for workarounds imho. I suggest a clean
One might have the intend to remove some amount, but during broadcast and confirmation there could be fills, resulting in an amount that exceeds what's offered. The initial intend probably doesn't change in this case, so I tend to "yes, let's do it this way". |
I am fine with your method as well Dexx. Currently I have: |
Now that I think of it: would it make sense to further differentiate between |
Sure Dexx. Suggest as many Cancel Action Types as possible. Assign numbers to them, easier to discuss. |
Well, let's see what the others think. But since we are speaking about using prices: it seems rather unhandy to use |
@m21: small note regarding INT64/INT64 -- since the default behavior as far as I know is to round down in such a case, you may take a special look at #170 (comment) which "ruled" divisions should round up.
|
I ran some queries against the current set of 16000+ MP transaction records in the Omniwallet database to get a feel for how many bytes of the txhash are needed to get a unique string. Here's what I found: First, the number of txhashes starting with each value of 0-F ranges from 961 to 1079, so the first char is pretty evenly distributed. The distribution is about the same for each of the next 6 characters (and others, I expect), as well. There are no duplicates when comparing the first 6 characters in the txhashes. Here's the number of collisions I found starting at the beginning of the txhash: by address, by address for tx51 issuer, and across the whole set of 16000+ transactions:
So, we should have confidence that in the vast majority of cases we'll be able to use the first 8 characters of the txhash to uniquely identify a tx21 belonging to a particular address (or any tx, for that matter). I chose 8 to increase the percentages in our favor, but it will likely be fewer than that. Put another way, the chance of a collision is (1/16) ^ N:
It's up to the front end to uniquely identify the tx21 to be affected. If there are 2 or more that match the substring, then the tx would be invalid. It is reasonable to identify the tx21 to be affected without having to come up with unit price matching fuzzy logic. |
Marv, you are awesome. Having data on this is superb!
Ahh, now I see: you took (hash, [address, [tx 51]]) into consideration and compared against any other hash. We can get away with much less, because we'd only need to match against someone's own transactions instead of any transaction ever made. The set to compare against can further be reduced by removing transactions that are no orders and even further by removing all transactions/orders that are no longer active: when I'd wish to publish an update/cancel/whatever for one of my active orders, then all I'd need to compare against are other active orders that I made in the past - because there is never the case where I'd update/cancel/x an order of someone else.
I'm not sure, if you suggest to use a fixed number - my idea was to adjust the length based on what's required to form an unique piece. Historical transactions are known, whether the set is solely based on no-longer-active orders of a single entity or any transaction ever made - this makes it possible to determine a sufficient length with 100 % confidence of no collision by testing a piece with length n against the set and increasing the length until there is no collision.
I object: a "take oldest/newest first" policy is very simple, yet effective and may reduce the set significantly. If this indeed resolves a conflict or reduce the required minimum length to satisfy the actual intend can be determined when creating a transaction, because full knowledge of historical transactions is given in this case, too.
I'm very curious, if @m21 is able to provide a solid solution for the "group and merge orders on a logical level based on price" approach due to the problems that may occure by using price as identifier, but if this is the case, then I believe it would offer greater flexibility. But that aside: I'm all in for adopting an "identify and select transaction by XX" mechanism for the traditional DEx or crowdsales - or let me rephrase: to use this mechanism to what you were looking for in #261: Allow users to specify the specific terms of an offer they are responding to and this could also be used to solve the underlying issue discussed in #132: Grace period after manually closing a crowdfund which I started for similar reasons. |
Guys, we specifically asked Craig and David to weigh on this issue last week, and they have ruled out TX hashes and the like. We are going with add/subtract logic. Additional cool cancel commands are fine if you want them, but further discussion of tx hashes and such are probably not going to be productive. @marv-engine - I think you had to leave early before that point in the meeting, but it was a pretty clear decision from the top which way we would go. The only thing left to do is codify the format in the spec. It may already be coded at this point, in which case, we need to match that. |
It seems I wasn't around for some critical details about all this, so it makes sense for someone who has all the details (@dacoinminster?) to write the spec PR. Feel free to incorporate any parts of my now outdated PR #271 if they're useful. |
No problemo. I think I've got a handle on what needs to happen. @m21 is this coded already? I don't want you to have to change your work . . . |
JR, all, roughly yes coded like this (currency is 32bit, amounts are 64bit as always): ADD given currency-pair & amount_got, amount_desired This part is up to you:
|
Just throwing it out there again:
If we're creating ratios (unit prices) why not specify them explicitly - amount_for_sale, unitprice |
Discussing lots on Skype - there is some good discussion and I see the flaw with unit prices (sell 1000 MSC for 1 satoshi total) though I consider perhaps a 0.00000001 minimum unit price. My main concern is this, the ratios (unit prices) we're coming up with are so precise that we will not be able to match them with future ADD/SUBTRACTS, example:
|
I think that behavior is fine, personally, as long as the user can tell the difference between the prices of two similar orders in the UI |
Sorry - I didn't answer Michael's 3 questions:
Remove youngest first makes sense to me.
The UI can always cancel-all at an effective price with a huge subtract, so I don't think we need a different command for this.
I'll try to put a flag in the spec which means cancel-all for a given currency pair. |
Actually @m21, there is no "newest" or "oldest" coins, since we are now merging orders. There is only one order at any given unit price. I think your question is actually whether we should change the datestamp when adding/subtracting coins. I think the answer is "no we should not". |
Pull request #276 is ready to go. Any further discussion goes there, I think, so I'm closing this issue. |
Internally there is, I believe. See my comment here for an example, because I was wondering about this, too: #270 (comment) |
I've been asked to implement MetaDex trading where orders are not restricted by this:
"An address cannot create a new sell order while that address has an active sell order with the same currencies in the same roles (for sale, desired)."
And I have. The trouble is in the Cancel. Perhaps issuing the same Trade order with same exact fields & parameters, but with the Cancel flag would do for multiple orders from the same Address.
If there was a partial sell at the price specified the rest of the order could still be canceled (or up to the amount remaining), etc.
The text was updated successfully, but these errors were encountered: