raiden-network / raidex Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
see /docs/api.md
Some thoughts on cleanup. Didn't give it too much thinking though. Please discuss.
raidex_node/
comittment_service/ (subfolder)
message_broker/ (subfolder)
raiden_mock/ (mocks the raiden API, we need this in order to test Raidex, consider to add this in Raiden)
The bar width should stay the same.
Why are there different distances between the bars?
A CS should spawn it's CommitmentServiceAdvertisements
to the broadcast while it is online.
This serves for discovery (later on), but most importantly:
A node doesn't need to know the current commitment-fee-rate beforehand and can observe and set it automatically. (He should know it for balance checks of a Commitment-Refund)
Implement way to track the trade history and latest price and so on.
Good place is properly the Offerbook
Improve the limit order like other strategy how to split up the offers.
React on offers not happening.
Support checking status of order, cancel the order.
Pythons decimal
module provides decimal fixed-point and floating-point arithmetic,
Decimal “is based on a floating-point model which was designed with people in mind, and necessarily has a paramount guiding principle – computers must provide an arithmetic that works in the same way as the arithmetic that people learn at school.” From the python doc
where the user has good controls over rounding and precision-behaviour.
In addition to that, the module offers "Signalling" for computations, indicating e.g. that a computation produced an Inexact or rounded result.
With this module it's also very easy to set quantizing behaviour (e.g. for grouping atomic offers into bigger chunks for UI-representation) on a per user basis to fit the users needs.
Look here for a first implementation of this using the decimal module.
The goal is to have all relevant numbers as decimal.Decimal
objects inside the application and
only encode them to strings for the user facing API.
The Offers and Trades needs to be grouped.
For example by roughly the same time, same price, so that it is not so much noise.
When submitting a lot of offers, I get the following error after some time (I assume the time it tries to resubmit for the first time):
ConnectionError: HTTPConnectionPool(host='localhost', port=5000): Max retries exceeded with url: /api/topics/c08b5542d177ac6686946920409741463a15dddb (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f1839c64c50>: Failed to establish a new connection: [Errno 11] Resource temporarily unavailable',))
<LimitOrderTask at 0x7f185a5ef050> failed with ConnectionError
To reproduce, add the following lines to __main__.py
:
from raidex.raidex_node.offer_book import OfferType
import random
for _ in range(1000):
node.limit_order(OfferType.BUY, int(1e18), random.randrange(1, 10000))
I assume that there are too many requests that take too long to process.
Will only be a dummy implementation for the first iteration
When adding more than a few offers, they seem to randomly disappear and come back again.
The easiest way to reproduce is to add the following lines in __main__.py
, start everything and refresh the UI at the right points in time:
from raidex.raidex_node.offer_book import OfferType
import random
for _ in range(20):
node.limit_order(OfferType.BUY, int(1e18), random.randrange(1, 10000))
I assume the reason is that the time between offer timeout and resubmission is too long. If during this dead time the UI requests the set of offers it gets an incomplete list.
In iteration 1 this will not support any sort of user authentication.
To save some space the explicit column of the Order-type should be excluded.
Instead, all text in the other columns should be coloured green/red according to their type.
This was started using PrimeNG's rowStyleClass
, but this is not yet working as expected.
The commitment service CS
helps two parties to commit to a token swap agreement prior to its execution. It helps to bring down the "free option" from minutes to a few seconds. It's implemented as a service in the public network. In order to interact with the commitment manager one needs to open a "channel" which allows to do off-chain commitments (value transfers).
It works as follows:
Maker
creates an Offer: O
Maker
hashes its offer H(O)
Maker
sends a signed "Maker Commitment" message MC
to CS
, saying it is committed up to certain timestamp T
to the offer O
. Part of it is a certain amount of ether as a deposit D
.CS
confirms a successful commitment by signing a message MCS = Signed([CM, committed_amount], CS)
. And a message signing the new channel credit (i.e. the updated number of tokens left to do commitments after deducting the now locked tokens for the recent commitment).Maker
broadcast the signed offer O
and the commitment MCS
Taker
sends a commitment TC
to CS
(see #16)CS
confirms as in 4) but signing TC
(instead of MC
), i.e. TCS = Signed(TC, CS)
CS
responds by a channel credit message refunding the commitmentTCS
. Maker and Taker eventually swap the tokens.CS
sends a channel credit message refunding the commitment (minus some fee) to each of the partiesCS
sends the a signed message indicating that the deal completed to the broadcast channel (this is used by the clients to learn which of the orders was executed, so they can have last prices).Notes:
O = [bid_token, bid_amount, ask_token, ask_amount, offer_id]
CM = Signed([H(O), timeout, remaining_deposit, channel_nonce], maker)
. the remaining_deposit
implicitly informs the CS
about the committed value.CC = Signed([amount, channel_nonce], CS)
CM = Signed([H(MCS), timeout, deposit_amount, channel_nonce], maker)
where timeout and deposit_amount must equal those in MC
.The API is a means to interact with the exchange in a high-level fashion:
It should work similarly than a normal exchange where you just place orders (Limit Order, Market Order) and a time the order is valid. The client handles the requests to the actual trusted parties and tries to construct multiple asset swaps in a way that the order is executed in a satisfactory fashion.
Maker sends a Commitment message (timeout) and follows it up with a raiden transfer to the CS.
If transfer arrives before the timeout, the CS sends a CommitmentProof
Taker sends a Commitment message (offer_id, offer_timeout) to the CS. Now the CS waits for a raiden transfer of the first taker. Once it arrives, the CS sends a CommitmentProof.
When a taker posts an Commitment to the CS but refuses to send the raiden transfer, he stalls the linked offer for other takers without any costs, what creates a free option.
This renders the whole exchange unusable, as it introduces a free option in the same order as an exchange without a CommitmentService
Every taker has to first transfer the commitment deposit to the CS and then sends the commitment message.
The CS accepts the first taker that manages to follow up the commitment deposit with a commitment message as the engaged taker.
This introduces a lot of transaction traffic on the CS and in the raiden network.
A lot of takers are competing for the cheapest offer.
Taker sends only a commitment deposit (offer-id) to the CS. The CS approves the first commitment deposit with a commitment proof. Other commitment deposits are put on a backlog queue and will be refunded as soon as feasible for the CS.
Potential takers are unsure about their state of engagement/commitment until they are refunded or receive the CommitmentProof.
This introduces a lot of transaction traffic on the CS and in the raiden network.
A lot of takers are competing for the cheapest offer. (But at least no additional Commitment message per taker-try).
This should allow failed takers to move on with their trading strategy and exclude the Offer from their Orderbook and will stop further traffic on the CS for this Offer.
Also the offer_id has potential collisions, since it is no enforced logic and chosen by the maker.
We should go through the repo and check all code if it is doing something and working
If code works, there should be a test for it and it should pass
if code doesnt work, if it is useful as pseudo code it should be marked as such and not break anything
or it should be removed.
If no one is willing to do this, we should remove all code and readd the parts later, that we need.
There are these kinds of messages:
The messages module will provide objects that allow for easy (de-)serialization.
_!!! Below is partially outdated. Please read the docstrings in https://github.com/ezdac/rex/blob/master/rex/messages.py_
Status: okay
An offer is published by a market maker and pushed to one ore more broadcast services.
Data
offer = rlp([ask_token, ask_amount, bid_token, bid_amount, offer_id, timeout])
timeout = <UTC milliseconds since epoch>
offer_sig = sign(sha3(offer), maker)
commitment = rlp([sha3(offer), amount])
commitment_sig = raiden signature of the commitment transfer by the committer
commitment_proof = sign(commitment_sig, cs)
cs = <commitment service ethereum address>
Broadcast
{
"msg": "offer",
"version": 1,
"data": "rlp([offer, offer_sig, commitment, commitment_sig, commitment_proof, cs])"
}
Status: revised
These can be send by the Commitment Service (CS) to broadcast services in order to announce its service to users.
Data:
address = <ethereum/raiden address>
commitment_asset = <asset_address of the accepted commitment currency>
fee_rate = <uint32 (fraction of uint32.max_int)>
Broadcast:
{
"msg": "commitment_service",
"data": rlp([address, commitment_asset, fee_rate]),
"version": 1
}
Users of the service have to expect to have a fee of
fee = int(uint32.max_int / fee_rate * commitment + 0.5)
deducted from each commitment.
An optional (unverifiable) statistics
field informing about the past performance could be discussed.
Status: revised
A Commitment is a commitment message sent to the CS, followed by a hashlocked (direct) raiden transfer from the maker to the commitment service. The secret for the hashlock is the hash of the offer (see above).
Data:
commitment = rlp(offer.offer_id, offer.timeout, amount)
hashlock = sha3(offer) # or offer.hash
If the transfer completes, the CS is expected to counter the commitment with a commitment proof (if the commitment is accepted) or to refund the committing party:
Data:
commitment_proof = sign(commitment_sig, cs)
After completing a swap, the traders can request the commitment to be released from the CS.
Data:
swap_execution = rlp([order_id, timestamp])
swap_execution_sig = sign(sha3(swap_confirmation), maker/taker))
Message Content:
swap_execution_notification = rlp([swap_execution, swap_execution_sig])
This needs to be send by both parties. After the CS received both swap_execution_notification
s it is expected to return the commitment (minus fees) to both trading parties.
Status: okay
A CS is expected to broadcast confirmed swaps in order to build its reputation.
Data:
swap_confirmation = rlp([order_id, timestamp])
swap_confirmation_sig = sign(sha3(swap_confirmation), cs)
Broadcast:
{
"msg": "swap_completed",
"version": 1,
"data": "rlp([swap_confirmation, swap_confirmation_sig])"
}
Trade History:
date|type|price|amount
Order Book:
Sell Orders | Bid Orders
Price Timeline Graph
Can be drawn based on trade history
Market Depth Graph
Can be drawn based on order book.
API provided:
Order Placement
Deferred for now
Implement a trading bot that will make orders and trade.
The bot mode should be a commandline option.
Probably some things from mocking can be reused
Elaborate if we can move all the scripts to angular-cli.json
ACK
message that indicates a successful processing of incoming messagesCommitment
-try with an ACK
before it will determine if the taker is engaged or not)The trading client should "subscribe" to the offer publishing service and create a "usable" order book, where "usable" means:
An order book is specific to one market.
API:
add_offer(offer_message)
amount
of both tokens (bid/ask), type
(buy/sell), offer_id
as well as a proof
of commitment (which must be evaluated) which contains a timeout
.remove_offer(offer_id)
get_orderbook(limit)
get_tradehistory(limit)
get_lastprice()
Will only be in memory, no actually network comuncation for first iteration, later flask or bottle
take a look at docs/api.md
or similar so that there is a difference between committing to a trade as a maker or taker.
Implement the communication with the commitment service in the raidex node
The zingchart's are not properly scaled to 100% of it's enclosing div-Element.
This should theoretically work with zing's width=100%
attribute.
Also compare here.
When an order is added by the user, the system spawns an OrderTask and returns an order_id which allows to interact with that task.
The task will try to fill the order by matching offers in the Offer View.
Limit Orders:
Market Orders:
Creating Orders:
AssetSwapRequests
(ASR
) with a given commitment-timeout, so that as long as the task is active and unfulfilled, there will always be an ASR
open in the network corresponding to the Order
. A task can be aborted, stopping it from spawning further subsequent ASRs. (Keep in mind: The latest ASR
will stay active and can't be aborted due to it's commitment based nature)In the price/stock/depthchart not all of the data should be plotted.
The question is if we should implement that in the webapp or in the node.
To reproduce: create a limit order, sleep for 5 seconds, cancel it.
Not sure if this is an issue of the UI or of the node.
The ExchangeTask need to take actions after a trade was done or failed.
The commitment service CS
acts as a trusted third party that helps two parties to commit to a raiden based token swap prior to its execution. This helps to bring down the "free option" from minutes to a few seconds. In order for a client (maker or taker), to interact with the CS
, it needs to open a direct raiden channel with the CS
. Only the client needs to deposit into this raiden channel. The client now has an amount of credit that it can use as commitments to the CS
. A direct raiden transfer from maker/taker to CS
represents a commit. As an initial suggestion the commitment amount should be 1/100 of the value the maker wants to trade. When the commitment service has received commitments from both the taker and the maker, it is up to the two parties to carry out the token exchange and report back to the CS
. The CS
will only redeem the commitment deposits if both the maker and the taker reports back that the transfer was successful within a specified timeout period.
Note: This implementation uses a simplified approach, where the third party is trusted with all commitments. In the worst case it could run away with all of them while the in #1 proposed solution the commitment deposits would only be at risk for a limited amount of time. We've chosen above as a preliminary approach to quickly get to a PoC. Nonetheless, this setup makes it more rewarding to be a dishonest 3rd party than #1.
It works as follows:
Maker
creates an Offer: O
Maker
hashes its offer H(O)
Maker
sends a signed "Maker Commitment" message MC
to CS
, saying it is committed up to certain timestamp T
to the offer O
.Maker
commits 1/100 of ask_amount
to the CS
in a raiden transfer.CS
confirms a successful commitment by signing a message MCS = Signed([MC, committed_amount], CS)
.Maker
broadcast the signed offer O
and the commitment MCS
Taker
directly sends a raiden-transfer(identifier=H(O))
to the CS
with the committed amount from the MCSCS
confirms the commitment to the sender of the first Taker-transfer by creating and signing TC
(instead of MC
), TC = Signed(C, CS)
, C = [ O, T, committer=taker_address ]
CS
responds by sending back the commitment in a raiden transfer(amount=commitment_amount - fee, identifier=H(O))
(from a backlog-queue, so maybe not immediately)TC
as a TCS = Signed(TC, Taker)
TCS
. Maker and Taker eventually swap the tokens.CS
refunds the commitments through raiden transfers (minus some fee) to each of the partiesCS
sends the a signed message indicating that the deal completed to the broadcast channel (this is used by the clients to learn which of the orders was executed, so they can have last prices).Notes:
O = [bid_token, bid_amount, ask_token, ask_amount, offer_id]
CM = Signed([H(O), timeout, commitment_id], maker)
where commitment_id
is the hashlockCM = Signed([H(MCS), timeout, commitment_id], taker)
where timeout and deposit_amount must equal those in MC
.C
is created by the commitment service, so the signing is reversed compared to the MCS
: TC
is signed by the CS
as an commitment proof, then TC
is signed by the taker as TCS
and broadcasted.TCS
for a given Taker
(this may not be an attack vector at all, who can gain from that?)** Below methods still need revision **
Methods:
Methods are implicitly called by sending messages to the service.
redeem_commitment(CM)
Send back the commitment corresponding to the CM
minus small fee through raiden transfer
commit(id, timeout, deposit)
commits user to execute an
Incoming offers should be filtered, so that only offers get in the orderbook that are
Restful API
see #3
Signer
Has the privkey of the user and can sign messages. Q: should we support multiple accounts?
Commitment Manager
<Outdated>
commit(commitment_service_address, offer_id, commitment_deposit, timeout)
announces an incoming commitment for offer_id to the CS
does a Raiden transfer, transferring the commitment (this is low latency for direct channels)
notify_success(commitment_service_address, offer_id)
sends a message stating that the exchange executed. the CS
will return the tokens if both parties say the exchange happened.
Note: we could require that both parties send the message they used to initiate the transfer, those proofing that they received the transfer, next to the secret for the hashlock. while this could be gamed (in the sense that they'd claim the deposit although they did not exchange) it would be hard to setup and not feasible unless upfront coordinated.
</Outdated>
See #10 "Commitment Announcement/Commitment Proof"
Raiden Client
see raiden api. unfortunately we need to poll for events.
Exchange
Implements the exchange logic for a token pairs, e.g. BeerCoin/ETH i.e. a market it interacts with..
Requirements: a user needs to have Raiden channels for both Tokens in the token-pair.
Needs to be listening to one ore more pub/sub services for this market.
Exchange collects the instances specific to a certain market.
instance of an exchange which features
The transport will:
address -> endpoint
mappingport = raiden-port+1
If there are a bigger number of offers in the offerbook, the offers sometimes dont get matched and the offerbook remains crossed.
It might be a race condition or a n error in the limited order code. Need to look into that.
After the commitment service is merged we should review the structure of the code and maybe reorganize it.
Find either a working version, or implement a ERC20 Token that allows locking ETH in exchange for tokens.
We should have more than one token pair that you can trade.
Should react on messages over the message broker system. Doesnt need transfers for the first iteration
Add an abstraction for the message broker on the client side that knows the senders address and does the encoding so we dont have encode_hex all over the code anymore.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.