Compare commits
119 commits
oxarbitrag
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
219b17a8aa | ||
|
792c524b2a | ||
|
4772b5a736 | ||
|
52eafc5a64 | ||
|
43831e0a05 | ||
|
dfb2ca516a | ||
|
6b923189cd | ||
|
bd1f839c7f | ||
|
a5d3b0208b | ||
|
b0b0be9592 | ||
|
4383ef74a7 | ||
|
87525f2496 | ||
|
3a053c4828 | ||
|
b767a530f2 | ||
|
d489b494bd | ||
|
fb068e7e1c | ||
|
f3ee7999f7 | ||
|
7ebd6ac361 | ||
|
9445500771 | ||
|
effbe1bcde | ||
|
c51a358a2d | ||
|
00e3c38ebf | ||
|
0d3e68f471 | ||
|
88f8af359f | ||
|
286e8ac44b | ||
|
75b47a4748 | ||
|
5ab1257b0b | ||
|
59507c2ea3 | ||
|
d1f7fbdbe4 | ||
|
52feaa1fc8 | ||
|
dfffa78782 | ||
|
4bd1dc5638 | ||
|
fd1c1a368b | ||
|
ba3b9d3255 | ||
|
4ed19a0414 | ||
|
326873130c | ||
|
d039e475b4 | ||
|
07af9adbf6 | ||
|
f040dd080f | ||
|
9599ba8817 | ||
|
f32a60c08e | ||
|
adb233735f | ||
|
344156ce36 | ||
|
5bf3ddc5f6 | ||
|
3831794d4e | ||
|
e3e8bd79b3 | ||
|
a57b3aa159 | ||
|
dac2335aa4 | ||
|
b5d70d616f | ||
|
e56ccde022 | ||
|
90c7abb725 | ||
|
2587dc7d49 | ||
|
623a6f9b8e | ||
|
dbb42ea8fb | ||
|
e22fe0e2d3 | ||
|
d6c7fdc785 | ||
|
a1b438c7e0 | ||
|
e82288f370 | ||
|
e8204f3a70 | ||
|
485df5cd4f | ||
|
8a06150338 | ||
|
52a530fd8e | ||
|
e3914d5f03 | ||
|
c4d424aa57 | ||
|
2bd11aedac | ||
|
cd459ee9d4 | ||
|
b00e7f33ab | ||
|
259fbe05ac | ||
|
58e11a7397 | ||
|
a52ca3919f | ||
|
2bbe6f836f | ||
|
ece1658e00 | ||
|
72c63d9ef6 | ||
|
e12c618a3f | ||
|
2f45346aac | ||
|
590a296fb6 | ||
|
9a841385bc | ||
|
1cf3cf894d | ||
|
dceedb9d43 | ||
|
27e1975b28 | ||
|
5fabc12f16 | ||
|
f220846900 | ||
|
21f3d15cbc | ||
|
b5e469742a | ||
|
4819d6be64 | ||
|
1f91ed3c9a | ||
|
219b3089b4 | ||
|
2474ee2fd2 | ||
|
2260bab020 | ||
|
f086fdfd37 | ||
|
09a6529d66 | ||
|
dcaa2e8891 | ||
|
f350d86af9 | ||
|
2255360034 | ||
|
c8be764e1f | ||
|
6579c464c2 | ||
|
b57ab21399 | ||
|
6878d6461f | ||
|
97ed075555 | ||
|
7480447b88 | ||
|
c6dbe1880e | ||
|
7f291d9b06 | ||
|
2723cc73b6 | ||
|
8bc2a40e46 | ||
|
a38836001c | ||
|
69ac9dc067 | ||
|
3a526a4109 | ||
|
6c89183bc3 | ||
|
54c1644310 | ||
|
30477cb3ff | ||
|
ed658d5c94 | ||
|
fdbd098dd4 | ||
|
eba090850f | ||
|
e062a351c2 | ||
|
2b214b2ffc | ||
|
1281d05215 | ||
|
25e935586e | ||
|
0045b5da94 | ||
|
cf781275af |
22 changed files with 2047 additions and 18 deletions
25
README.md
25
README.md
|
@ -25,14 +25,29 @@ Number | Title |
|
|||
[15](bsip-0015.md) | Disable negative voting on workers | Daniel Larimer | Protocol | Installed
|
||||
[16](bsip-0016.md) | Optimization to Force Settlement Parameters of BitCNY | Jerry Liu | Protocol | Installed
|
||||
[17](bsip-0017.md) | Revive BitAsset after Global Settlement | Peter Conrad | Protocol | Draft
|
||||
[18](bsip-0018.md) | Revive BitAsset through buying Settlement Pool | Fabian Schuh | Protocol | Implemented
|
||||
[19](bsip-0019.md) | Introducing profit sharing/dividends to Bitshares (MPA only) | Customminer | Protocol | Rejected
|
||||
[20](bsip-0020.md) | Introducing profit sharing/dividends to Bitshares (UIA only) | Customminer | Protocol | Rejected
|
||||
[18](bsip-0018.md) | Revive BitAsset through buying Settlement Pool | Fabian Schuh | Protocol | Installed
|
||||
[19](bsip-0019.md) | Introducing profit sharing/dividends to Bitshares (MPA only) | Customminer | Protocol | Deferred
|
||||
[20](bsip-0020.md) | Introducing profit sharing/dividends to Bitshares (UIA only) | Customminer | Protocol | Deferred
|
||||
[21](bsip-0021.md) | Introducing the 'Coin-Age' statistic to Bitshares assets | Customminer | Protocol | Draft
|
||||
[22](bsip-0022.md) | Introducing expiring votes for Witnesses, Committie members & Proxies within the Bitshares network | Customminer | Protocol | Draft
|
||||
[23](bsip-0023.md) | Sharedropping an UIA against an external cryptocurrency distribution snapshot | Customminer | Protocol | Draft
|
||||
[24](bsip-0024.md) | Locking Bitshares away as 'Bitshares Influence' for voting privileges on the BTS DEX | Customminer | Protocol | Draft
|
||||
[25](bsip-0025.md) | Transaction Flat-Rates with Weighted Rate-Limitation | Fabian Schuh | Protocol | Draft
|
||||
[26](bsip-0026.md) | Refund Order Creation Fee in Originally Paid Asset on Cancel | Abit More | Protocol | Draft
|
||||
[27](bsip-0027.md) | Asset Issuer Reclaim Fee Pool Funds | Abit More | Protocol | Draft
|
||||
[26](bsip-0026.md) | Refund Order Creation Fee in Originally Paid Asset on Cancel | Abit More | Protocol | Accepted
|
||||
[27](bsip-0027.md) | Asset Issuer Reclaim Fee Pool Funds | Abit More | Protocol | Accepted
|
||||
[28](bsip-0028.md) | Worker Proposal Improvements | Bill Butler | Protocol | Draft
|
||||
[29](bsip-0029.md) | Asset issue change to require owner authority | Fabian Schuh | Protocol | Accepted
|
||||
[30](bsip-0030.md) | Always Allow Increasing Collateral Ratio If Debt Not Increased | Abit More | Protocol | Accepted
|
||||
[31](bsip-0031.md) | Update Short Position's Margin Call Price After Partially Called Or Settled | Abit More | Protocol | Accepted
|
||||
[32](bsip-0032.md) | Always Match Orders At Maker Price | Abit More | Protocol | Accepted
|
||||
[33](bsip-0033.md) | Maker Orders With Better Prices Take Precedence | Abit More | Protocol | Accepted
|
||||
[34](bsip-0034.md) | Always Trigger Margin Call When Call Price Above Or At Price Feed | Abit More | Protocol | Accepted
|
||||
[35](bsip-0035.md) | Mitigate Rounding Issue On Order Matching | Abit More | Protocol | Accepted
|
||||
[36](bsip-0036.md) | Remove expired price feeds on maintenance interval | oxarbitrage | Protocol | Accepted
|
||||
[37](bsip-0037.md) | Allow new asset name to end with a number | oxarbitrage | Protocol | Accepted
|
||||
[1200](bsip-1200.md) | Stealth development, Phase II | Chris Sanborn | Informational | Draft
|
||||
[1201](bsip-1201.md) | New operations for Confidential Asset (CA) transactions | Chris Sanborn | Protocol | Draft
|
||||
[1202](bsip-1202.md) | Ring signatures for untraceability of Stealth transactions | Chris Sanborn | Protocol | Draft
|
||||
[1203](bsip-1203.md) | Blockchain scanning for inbound Stealth transactions | Chris Sanborn | Protocol | Draft
|
||||
[1204](bsip-1204.md) | Deterministic addresses for Stealth wallets | Chris Sanborn | Informational | Draft
|
||||
[1205](bsip-1205.md) | Metadata hiding via Garlic Routing and other means | Chris Sanborn | Informational | Draft
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
BSIP: 00018
|
||||
BSIP: 0018
|
||||
Title: Revive BitAsset through buying Settlement Pool
|
||||
Authors: Fabian Schuh, Peter Conrad
|
||||
Status: Implemented
|
||||
Status: Installed
|
||||
Type: Protocol
|
||||
Created: 2017-06-05
|
||||
Discussion: https://bitsharestalk.org/index.php/topic,24322.0.html
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
BSIP: #019
|
||||
Title: Introducing profit-sharing/dividends to Bitshares (MPA only)
|
||||
Authors: [Customminer](https://steemit.com/@cm-steem/)
|
||||
Status: Rejected
|
||||
Status: Deferred
|
||||
Type: Protocol
|
||||
Created: 2017-06-18
|
||||
Primary Discussion: https://bitsharestalk.org/index.php/topic,23981.0.html
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
BSIP: #020
|
||||
Title: Introducing profit-sharing/dividends to Bitshares (UIA only)
|
||||
Authors: [Customminer](https://steemit.com/@cm-steem/)
|
||||
Status: Rejected
|
||||
Status: Deferred
|
||||
Type: Protocol
|
||||
Created: 2017-06-26
|
||||
Primary Discussion: https://bitsharestalk.org/index.php/topic,23981.0.html
|
||||
|
|
175
bsip-0025.md
Normal file
175
bsip-0025.md
Normal file
|
@ -0,0 +1,175 @@
|
|||
BSIP: 00025
|
||||
Title: Transaction Flat-Rates with Weighted Rate-Limitation
|
||||
Authors: Fabian Schuh <Fabian.Schuh@blockchainprojectsbv.com>
|
||||
Status: Draft
|
||||
Type: Protocol
|
||||
Created: 2017-10-16
|
||||
Worker: T.B.D.
|
||||
|
||||
# Abstract
|
||||
|
||||
Blockchain technology currently depends upon transaction fees to prevent
|
||||
spam. These fees suffer all of the known problems with
|
||||
micro-transactions and prevent blockchains from being used for low-value
|
||||
transactions, massive trading and high-rate market making. Truly
|
||||
decentralized applications must offer users the *appearance* of free
|
||||
transactions if they wish to compete with their centralized
|
||||
alternatives.
|
||||
|
||||
This document proposes a protocol upgrade to BitShares to introduce
|
||||
rate-limitations for *fee-free* transactions. Since the BitShares
|
||||
blockchain is entitled to be a profitable decentralized autonomous
|
||||
company (DAC), making use of *fee-free* transactions comes at a
|
||||
*monthly* fixed cost as well as the option to lock shares away in a
|
||||
vesting balance in order to increase the standard rate at which users
|
||||
may interact with the blockchain.
|
||||
|
||||
# Motivation
|
||||
|
||||
Blockchains are decentralized networks where all transactions are
|
||||
broadcast to all peers. Every so often a block is produced that includes
|
||||
some or all of the pending transactions. All blockchains must find a
|
||||
solution to prevent malicious users from consuming all of the available
|
||||
network capacity with worthless transactions. These worthless
|
||||
transactions can prevent other valuable transactions from being
|
||||
processed and ultimately destroy the network.
|
||||
|
||||
The solution adopted by most blockchains thus far is to charge a minimum
|
||||
transaction fee. A fee worth just a few cents is enough to make
|
||||
attacking the network expensive and unprofitable. While this approach
|
||||
solves the spam problem, it introduces new problems.
|
||||
|
||||
Market making as well as micro-transactions are a highly competitive
|
||||
market. Being *decentralized* and *trust-less* alone, does not make the
|
||||
BitShares blockchain a good competitor when compared to centralized
|
||||
services.
|
||||
|
||||
Despite blockchain transactions being cheaper *technically*, the fee
|
||||
that is attached to each and every transaction on BitShares results in
|
||||
some crucial businesses to be unviable, such as **market making** at
|
||||
scale, where dozens of orders are created (and canceled) continuously,
|
||||
in order to provide liquidity to the markets.
|
||||
|
||||
# Rational
|
||||
|
||||
In this proposal, we extend the BitShares fee model to allow
|
||||
transactions made by accounts to go through without paying a fee. We
|
||||
require accounts to be lifetime members to harness a **transaction
|
||||
flat-rate** with certain limits that can be raised by additionally
|
||||
providing BTS (units of the core asset) in a vesting balance that is
|
||||
locked away for a certain amount of time, only do be made liquid in
|
||||
weekly chunks over the whole period.
|
||||
|
||||
## Full Reserve vs Fractional Reserve
|
||||
|
||||
Let's view a blockchain like an Internet Service Provider (ISP) co-op
|
||||
which owns all of the cables in the town and can process a maximum
|
||||
amount of data transmission on those cables at any time. This is called
|
||||
*the capacity* of the transmission lines. People living in the town can
|
||||
buy shares in the ISP and obtain the right to utilize a portion of the
|
||||
available capacity.
|
||||
|
||||
The ISP has two choices and can either run a **full reserve** or
|
||||
**fractional reserve** system.
|
||||
|
||||
* Under a full reserve system each user is only allowed a fraction of
|
||||
the capacity proportional to her shares. Because not everyone uses
|
||||
the Internet at the same time, the town's network would be significantly
|
||||
underutilized.
|
||||
* Under a fractional reserve system the individual users could utilize
|
||||
more date rate than they are entitled to at any given point in time so
|
||||
long as not everyone uses the Internet at the same time.
|
||||
|
||||
The problem with operating a fractional reserve is that congestion
|
||||
occurs anytime too many people wish to use the network at the same time.
|
||||
The ISP needs a way to prioritize transmissions during congested
|
||||
periods. In the most extreme case, a fully congested network must revert
|
||||
to a full reserve system.
|
||||
|
||||
The challenge is setting the proper fractional reserve ratio or
|
||||
implement a **dynamic fractional reserve ratio**. Under this model the
|
||||
blockchain will
|
||||
automatically adjust the reserve ratio for the network during times of
|
||||
congestion. The blockchain will set a target utilization that leaves
|
||||
enough headroom for short term surges in demand. Any time the surges
|
||||
are sustained the blockchain reduces the maximum rate-per-share.
|
||||
When a surge is over and there is surplus capacity the blockchain can
|
||||
slowly increase the rate-per-share.
|
||||
|
||||
If the time window for this control cycle is stretched too far then the
|
||||
reserve ratio will not adjust fast enough to respond to short-term
|
||||
surges, if the window is too short then clustering usage will have too
|
||||
big of an impact on normal users.
|
||||
|
||||
In our estimate it should be sufficient to measure the average weekly
|
||||
transaction rate usage of users. This parameter will be changeable by
|
||||
the BitShares committee. The advantage with this approach is, that the
|
||||
BitShares committee can define whether they prefer a dynamic fractional
|
||||
reserve, where occasional uses may transact more often within a very
|
||||
short period of time, or a simple and static method, where professional
|
||||
users get an easy picture of how many transactions they may produce in a
|
||||
certain amount of time.
|
||||
|
||||
## Flat-Rate Model
|
||||
|
||||
In recent years, ISP providers have seen a shift in their own economics
|
||||
leaving the *pay-per-use* (e.g. per minute) service domain where users
|
||||
paid for a duration they occupied a land-line to go for a
|
||||
*pay-per-serice* flat-rate model where users paid a fixed fee to enable
|
||||
a specific service to be used for free within certain conditions (e.g.
|
||||
data volume). With the improvements in communications technology, land
|
||||
lines got replaced by fiber which can carry significantly more load.
|
||||
Thus the flat-rate model makes sense from business perspective.
|
||||
|
||||
The same holds true for blockchain technologies. The Graphene framework
|
||||
is capable of incomparable transaction loads and thus, the individual
|
||||
transaction may not be tagged with a fee for the profit alone, but
|
||||
merely to prevent spam. A full reserve system gives value to a
|
||||
transaction processing capabilities of the blockchain which everyone can
|
||||
own a share of to prevent spam.
|
||||
|
||||
## Flat-Rate with Weighted Rate-Limitation
|
||||
|
||||
That said, we here propose a combination of the flat-rate model with a
|
||||
stake-weighted limitation of transaction rates.
|
||||
|
||||
* **Flat-Rate**: A new feature is added to the blockchain that enables
|
||||
the flat-rate model with a basic transaction rate that can be defined
|
||||
by the BitShares committee (e.g. 10 transactions per day). This
|
||||
operation costs a fee and lasts for a committee-parameterized amount
|
||||
of time (e.g. 30 days). These rates are the same for every single user
|
||||
that has bought the flat-rate subscription.
|
||||
|
||||
* **Stake-Weighting**: Since some users may need more than the basic
|
||||
amount of transactions per day, power users can increase the
|
||||
implicitly assumed weight of 1x to a higher value by providing BTS
|
||||
core tokens in a vesting balance locks them away for as long as the
|
||||
subscription lasts.
|
||||
|
||||
This ultimately gives the option to
|
||||
|
||||
* pay a fee for every transaction (current system)
|
||||
* pay for a flat-rate to transaction for fee within certain conditions
|
||||
* powerup your account with core tokens to increase fee transaction
|
||||
rate
|
||||
|
||||
# Specifications
|
||||
|
||||
* Do not refund order creation fee!
|
||||
* Replace Annual Fee operation?
|
||||
|
||||
# Discussion
|
||||
|
||||
Todo
|
||||
|
||||
# Summary for Shareholders
|
||||
|
||||
Todo
|
||||
|
||||
# Copyright
|
||||
|
||||
This document is placed in the public domain.
|
||||
|
||||
# See Also
|
||||
|
||||
1. [Steem Whitepaper](https://steem.io/SteemWhitePaper.pdf)
|
|
@ -1,12 +1,12 @@
|
|||
BSIP: 0026
|
||||
Title: Refund Order Creation Fee in Originally Paid Asset on Cancel
|
||||
Authors: Abit More <https://github.com/abitmore>
|
||||
Status: Draft
|
||||
Status: Accepted
|
||||
Type: Protocol
|
||||
Created: 2017-10-16
|
||||
Discussion: https://bitsharestalk.org/index.php/topic,25153.0.html
|
||||
Replaces: 0002
|
||||
Worker: TBD
|
||||
Worker: 1.14.69
|
||||
|
||||
# Abstract
|
||||
|
||||
|
|
25
bsip-0027.md
25
bsip-0027.md
|
@ -2,11 +2,11 @@
|
|||
Title: Asset Issuer Reclaim Fee Pool Funds
|
||||
Authors: Abit More <https://github.com/abitmore>
|
||||
Fabian Schuh <Fabian@BitShares.eu>
|
||||
Status: Draft
|
||||
Status: Accepted
|
||||
Type: Protocol
|
||||
Created: 2017-11-02
|
||||
Discussion: https://github.com/bitshares/bitshares-core/issues/188
|
||||
Worker: TBD
|
||||
Worker: 1.14.70
|
||||
|
||||
# Abstract
|
||||
|
||||
|
@ -40,17 +40,28 @@ The `amount` in the structure can only be positive, which means the `from_accoun
|
|||
|
||||
## Proposed Changes
|
||||
|
||||
* Allow `amount` to be negative;
|
||||
* When `amount` is negative, `from_account` can only be the issuer;
|
||||
* When `amount` is negative, deduct the absolute amount from the asset's fee pool and add it to the issuer's balance.
|
||||
We propose to add a new operation `asset_claim_pool_operation` that allows to claim CORE asset (BTS) from the fee pool.
|
||||
|
||||
```
|
||||
struct asset_claim_pool_operation : public base_operation
|
||||
{
|
||||
asset fee;
|
||||
account_id_type issuer;
|
||||
asset_id_type asset_id; /// fee.asset_id must != asset_id
|
||||
asset amount_to_claim; /// core asset
|
||||
extensions_type extensions;
|
||||
};
|
||||
```
|
||||
|
||||
We've decided to add a new operation in order to no modify existing behavior.
|
||||
|
||||
# Discussion
|
||||
|
||||
The operation fee for `asset_fund_fee_pool_operation ` should be no less than `transfer_operation`.
|
||||
The operation fee for `asset_claim_pool_operation ` should be no less than `transfer_operation`.
|
||||
|
||||
# Summary for Shareholders
|
||||
|
||||
[to be added]
|
||||
We here propose the addition of a new operation that allows to claim fees from the fee pool. Since the fee pools are pre-filled with an initial amount from the asset creation fee, this feature is useful for those that do not desire to use the fee pool.
|
||||
|
||||
# Copyright
|
||||
|
||||
|
|
97
bsip-0029.md
Normal file
97
bsip-0029.md
Normal file
|
@ -0,0 +1,97 @@
|
|||
BSIP: 0029
|
||||
Title: Asset issue change to require owner authority
|
||||
Authors: Fabian Schuh <Fabian.Schuh@blockchainprojectsbv.com>
|
||||
Status: Accepted
|
||||
Type: Protocol
|
||||
Created: 2018-01-28
|
||||
Discussion: https://github.com/bitshares/bitshares-core/issues/199
|
||||
Worker: 1.14.81
|
||||
|
||||
# Abstract
|
||||
|
||||
With the current design, the issuer of an asset can be changed with the
|
||||
*active authority* alone. However, this authority is also required for
|
||||
issuing new units of an asset/token. If this process wants to be
|
||||
automated, an active key needs to be stored on an internet-connected
|
||||
device. If compromised, an attacker can easily move the asset under his
|
||||
control with no way to back.
|
||||
|
||||
This proposal comes with two changes to the protocol:
|
||||
|
||||
1. The current behavior of changing an assets' parameters will no longer
|
||||
allow to change the issuer.
|
||||
2. A new operation is introduced that allows to change the issuer of an
|
||||
asset but requires the owner authority of the issuer to sign that
|
||||
transaction.
|
||||
|
||||
# Motivation
|
||||
|
||||
Improve asset security.
|
||||
|
||||
# Rational
|
||||
|
||||
Assets should not be at risk while automating issuing of new units.
|
||||
|
||||
# Specifications
|
||||
|
||||
## Current Design and Implementation
|
||||
|
||||
Currently, any asset can be updated with `asset_update_operation`. This
|
||||
operation contains an optional `new_issuer` that changes the issuer of
|
||||
the asset.
|
||||
|
||||
## Proposed Changes
|
||||
|
||||
# `asset_update_operation`
|
||||
|
||||
The existing `asset_update_operation` will be modified in such that it
|
||||
no longer allows the user of `new_issuer` after a hard fork.
|
||||
|
||||
# `asset_update_issuer_operation`
|
||||
|
||||
A new operation is added with the following construction
|
||||
|
||||
```
|
||||
|
||||
struct asset_update_issuer_operation : public base_operation
|
||||
{
|
||||
struct fee_parameters_type {uint64_t fee = 20 * GRAPHENE_BLOCKCHAIN_PRECISION; };
|
||||
|
||||
asset fee;
|
||||
account_id_type issuer;
|
||||
asset_id_type asset_to_update;
|
||||
account_id_type new_issuer;
|
||||
extensions_type extensions;
|
||||
|
||||
account_id_type fee_payer()const { return issuer; }
|
||||
void validate()const;
|
||||
|
||||
void get_required_owner_authorities( flat_set<account_id_type>& a )const
|
||||
{ a.insert( issuer ); }
|
||||
|
||||
void get_required_active_authorities( flat_set<account_id_type>& a )const
|
||||
{ }
|
||||
|
||||
};
|
||||
```
|
||||
|
||||
This new operation merely allows to change the issuer of an asset and
|
||||
requires the owner authority (of the issuer account) to sign the
|
||||
transaction.
|
||||
|
||||
# Summary for Shareholders
|
||||
|
||||
We here propose the addition of a new operation that improves security
|
||||
of assets with respect to updating the issuer. This closes a long
|
||||
existing problem that makes running automated issuing of units a
|
||||
security issue since an attacker that obtains the keys can obtain full
|
||||
control of an asset indefinitely. This proposal changes this behavior
|
||||
and requires the owner to sign such change of issuer.
|
||||
|
||||
# Copyright
|
||||
|
||||
This document is placed in the public domain.
|
||||
|
||||
# Sponsoring
|
||||
|
||||
This worker proposal is proudly presented and sponsored by [Blockchain Projects BV](http://blockchainprojectsbv.com).
|
71
bsip-0030.md
Normal file
71
bsip-0030.md
Normal file
|
@ -0,0 +1,71 @@
|
|||
BSIP: 0030
|
||||
Title: Always Allow Increasing Collateral Ratio If Debt Not Increased
|
||||
Author: Abit More <https://github.com/abitmore>
|
||||
Status: Accepted
|
||||
Type: Protocol
|
||||
Created: 2018-02-16
|
||||
Discussion: https://github.com/bitshares/bitshares-core/issues/583,
|
||||
https://github.com/bitshares/bitshares-core/issues/672
|
||||
Replaces: -
|
||||
Worker: 1.14.91
|
||||
|
||||
# Abstract
|
||||
|
||||
Currently, when a short position's collateral ratio is below MCR (a parameter
|
||||
in price feed: `maintenance_collateral_ratio`) but is not completely filled
|
||||
immediately due to a lack of enough volume on the opposite side of the market,
|
||||
it will hang in the market and be waiting for being margin called.
|
||||
|
||||
The owner then can adjust the order's collateral ratio **only if**
|
||||
* to close the position, or
|
||||
* the new collateral ratio is above MCR, or
|
||||
* the call order get completely filled (margin called) immediately.
|
||||
|
||||
While this prevents shorters from maliciously reducing collateral ratio (to
|
||||
increase possibility of black swan event), it also prevents shorters from
|
||||
slightly increasing collateral ratio (to decrease possibility of black swan
|
||||
event).
|
||||
|
||||
This BSIP proposes a mechanism to improve this situation.
|
||||
|
||||
# Motivation
|
||||
|
||||
Make the exchange system more user-friendly.
|
||||
|
||||
# Rationale
|
||||
|
||||
The ecosystem would get benefit if shorters are allowed to reduce risks to
|
||||
themselves while reducing risks to the system at same time.
|
||||
|
||||
Current rules are a bit too strict, which can be loosed to:
|
||||
|
||||
A shorter can adjust the position's collateral ratio **only if**
|
||||
* to close the position, or
|
||||
* the new collateral ratio is above MCR, or
|
||||
* the call order get completely filled (margin called) immediately, or
|
||||
* **the new ratio is higher than old ratio and debt is not increased**
|
||||
|
||||
# Specifications
|
||||
|
||||
In `do_apply()` function of `call_order_update_evaluator` class, if
|
||||
finally found the call order still in margin call territory,
|
||||
* don't throw an exception if `call_obj->collateralization()` is reduced, and
|
||||
* require `delta_debt` of `call_order_update_operation` to be non-positive.
|
||||
|
||||
# Discussion
|
||||
|
||||
[to be added if any]
|
||||
|
||||
# Summary for Shareholders
|
||||
|
||||
[to be added if any]
|
||||
|
||||
# Copyright
|
||||
|
||||
This document is placed in the public domain.
|
||||
|
||||
# See Also
|
||||
|
||||
* https://github.com/bitshares/bitshares-core/issues/583
|
||||
* https://github.com/bitshares/bitshares-core/issues/672
|
||||
* https://bitsharestalk.org/index.php?topic=25926.0
|
65
bsip-0031.md
Normal file
65
bsip-0031.md
Normal file
|
@ -0,0 +1,65 @@
|
|||
BSIP: 0031
|
||||
Title: Update Short Position's Margin Call Price After Partially Called Or Settled
|
||||
Author: Abit More <https://github.com/abitmore>
|
||||
Status: Accepted
|
||||
Type: Protocol
|
||||
Created: 2018-02-16
|
||||
Discussion: https://github.com/bitshares/bitshares-core/issues/343,
|
||||
https://github.com/bitshares/bitshares-core/issues/649
|
||||
Replaces: -
|
||||
Worker: 1.14.92
|
||||
|
||||
# Abstract
|
||||
|
||||
Currently, when a short position get partially called or settled, the call
|
||||
price won't change, that said, even if its actual collateral ratio is higher
|
||||
than others, higher than minimum required, it will still be selling collateral
|
||||
at a low price, taking precedence over other short positions.
|
||||
|
||||
This behavior is causing several issues:
|
||||
* it's somehow unfair, thus brought bad experience to shorters, and
|
||||
* it prevents black swan event from being triggered in time when needed,
|
||||
because the collateral ratio of the 2nd even overall short positions may
|
||||
be too low but not being checked, thus risks the pegging system.
|
||||
|
||||
This BSIP proposes a mechanism to improve this situation.
|
||||
|
||||
# Motivation
|
||||
|
||||
Make the exchange system more user-friendly.
|
||||
|
||||
# Rationale
|
||||
|
||||
To attract more users, the system should be fair, should be well balanced.
|
||||
|
||||
It's common sense that short positions with least collateral ratio should
|
||||
get margin called first. This can be achieved if always update the margin
|
||||
call price after every fill.
|
||||
|
||||
# Specifications
|
||||
|
||||
In `fill_order( const call_order_object& ...)` function of `database` class,
|
||||
update `call_price` field of `call_order_object` after debt or collateral
|
||||
changed to a non-zero value.
|
||||
|
||||
In addtion, after `call_price` get updated, the iterators initialized with
|
||||
`by_price` index may be invalidated, so need to review / revise involved code,
|
||||
E.G. `check_call_orders(...)` function of `database` class.
|
||||
|
||||
# Discussion
|
||||
|
||||
[to be added if any]
|
||||
|
||||
# Summary for Shareholders
|
||||
|
||||
[to be added if any]
|
||||
|
||||
# Copyright
|
||||
|
||||
This document is placed in the public domain.
|
||||
|
||||
# See Also
|
||||
|
||||
* https://github.com/bitshares/bitshares-core/issues/343
|
||||
* https://github.com/bitshares/bitshares-core/issues/649
|
||||
* https://bitsharestalk.org/index.php?topic=25926.0
|
104
bsip-0032.md
Normal file
104
bsip-0032.md
Normal file
|
@ -0,0 +1,104 @@
|
|||
BSIP: 0032
|
||||
Title: Always Match Orders At Maker Price
|
||||
Author: Abit More <https://github.com/abitmore>
|
||||
Status: Accepted
|
||||
Type: Protocol
|
||||
Created: 2018-02-16
|
||||
Discussion: https://github.com/bitshares/bitshares-core/issues/338
|
||||
Replaces: -
|
||||
Worker: 1.14.93
|
||||
|
||||
# Abstract
|
||||
|
||||
Currently, under most circumstances, when matching two orders, the maker price
|
||||
will be used to calculate how much each order will pay and receive.
|
||||
However, when matching a taker limit order with a maker margin call order,
|
||||
the taker price is being used.
|
||||
|
||||
This BSIP proposes a principle: always match orders at maker price.
|
||||
|
||||
# Motivation
|
||||
|
||||
Generally, the order that is placed earlier (the maker) sets a price,
|
||||
another order that is placed later (the taker) accepts the price, thus a match,
|
||||
two orders pay to each other at that price.
|
||||
|
||||
Take the pure limit order matching mechanism in BitShares as an example:
|
||||
If one person (A) placed a limit
|
||||
order to sell 100 BTS at 0.1 USD per BTS, another person (B) then placed a new
|
||||
limit order to buy 100 BTS at 0.105 USD per BTS, the two orders will match at
|
||||
0.1 USD per BTS, so A will pay 100 BTS and get 10 USD, B will pay 10 USD and
|
||||
get 100 BTS.
|
||||
|
||||
However, in BitShares, when matching a taker limit order with a maker margin
|
||||
call order, the taker price is being used.
|
||||
For example, if trader A's margin call order is
|
||||
selling 100 BTS at no less than 0.1 USD per BTS, then trader B placed an order
|
||||
that buys 100 BTS at 0.105 USD per BTS, the two order will match at 0.105 USD
|
||||
per BTS, so A will pay 100 BTS and get 10.5 USD, B will pay 10.5 USD and get
|
||||
100 BTS.
|
||||
|
||||
While not strictly a bug, this behavior is unexpected and irritating for users.
|
||||
|
||||
# Rationale
|
||||
|
||||
Matching orders at the maker price, with margin calls being inlined in the
|
||||
order book, is an easy to understand rule and matches user expectations,
|
||||
see [bitshares-core
|
||||
issue #338](https://github.com/bitshares/bitshares-core/issues/338).
|
||||
|
||||
There is a parameter in price feed named MSSR, which stands for "maximum short
|
||||
squeeze ratio". Maker price of margin call orders is MSSP, which stands for
|
||||
"maximum short squeeze price", is calculated as `feed_price / MSSR`.
|
||||
Note: `feed_price` here is in terms of debt/collateral, aka "how much debt per
|
||||
collateral".
|
||||
|
||||
Currently a black swan event will occur when the call order with least
|
||||
collateral ratio is going to be matched below 100% collateral ratio price
|
||||
(name it `100CRP`). Because the call order will be matched with incoming limit
|
||||
order at limit order's price (taker price),
|
||||
which can be higher or lower than 100CRP, so even if MSSP is below 100CRP,
|
||||
an incoming taker limit order may or may not trigger a black swan.
|
||||
So it makes sense to check if a black swan event will occur every time when a
|
||||
limit order is created.
|
||||
|
||||
After the behavior changed to always match at maker price, when MSSP is below
|
||||
100CRP, an incoming taker limit order will always trigger a black swan event.
|
||||
So it makes sense to trigger the black swan event when MSSP is below 100CRP
|
||||
rather than waiting for an incoming limit order. That means it's no longer
|
||||
needed to check for black swan event when a limit order is created.
|
||||
Since checking for black swan event is somehow expensive, we'll gain a side
|
||||
benefit on performance with the change.
|
||||
|
||||
# Specifications
|
||||
|
||||
Matching between a limit order and a call order is done in
|
||||
`check_call_orders(...)` function of `database` class, price of limit order
|
||||
is always used. It need to be changed to use MSSP when the call order is maker.
|
||||
|
||||
When triggering a black swan event when MSSP is below 100CRP,
|
||||
sometimes the short
|
||||
position with least collateral ratio may still have more than 100% collateral
|
||||
ratio. In this case, the global settlement price is 100CRP but not the actual
|
||||
collateral ratio of the short position with least collateral ratio.
|
||||
This is current behavior, it's fair, no need to change.
|
||||
|
||||
# Discussion
|
||||
|
||||
It might seem unfair on the shorter to match at MSSP even if the incoming order
|
||||
specifies a better price. However, in a rationally acting market users will not,
|
||||
in the presence of margin calls, create limit orders below the MSSP.
|
||||
Effectively the new rule doesn't change this situation.
|
||||
|
||||
# Summary for Shareholders
|
||||
|
||||
[to be added if any]
|
||||
|
||||
# Copyright
|
||||
|
||||
This document is placed in the public domain.
|
||||
|
||||
# See Also
|
||||
|
||||
* https://github.com/bitshares/bitshares-core/issues/338
|
||||
* https://bitsharestalk.org/index.php?topic=25926.0
|
136
bsip-0033.md
Normal file
136
bsip-0033.md
Normal file
|
@ -0,0 +1,136 @@
|
|||
BSIP: 0033
|
||||
Title: Maker Orders With Better Prices Take Precedence
|
||||
Author: Abit More <https://github.com/abitmore>
|
||||
Status: Accepted
|
||||
Type: Protocol
|
||||
Created: 2018-02-17
|
||||
Discussion: https://github.com/bitshares/bitshares-core/issues/625,
|
||||
https://github.com/bitshares/bitshares-core/issues/453
|
||||
Replaces: -
|
||||
Worker: 1.14.94
|
||||
|
||||
# Abstract
|
||||
|
||||
Currently, in BitShares, under certian circumstances, a taker order may be
|
||||
matched with a maker order which is not "on the top" of the order book.
|
||||
This behavior is unexpected and irritating for users.
|
||||
|
||||
This BSIP proposes a principle: always match taker orders with maker orders
|
||||
with the best prices (aka on the top of the order book) first.
|
||||
|
||||
# Motivation
|
||||
|
||||
As expected, when matching taker limit orders with maker limit orders, the maker
|
||||
limit orders with better prices will always be matched first.
|
||||
|
||||
For example, if trader A has a limit order selling 100 BTS at
|
||||
0.1 USD per BTS, trader B has a limit order selling 100 BTS at 0.09 USD per BTS,
|
||||
which means B's limit order has a better price for the opposite side to buy.
|
||||
Now if trader C placed an order that buys 10 BTS at 0.105 USD per BTS, B's
|
||||
limit order will take precedence, A's limit order won't be matched.
|
||||
|
||||
However, when there are (maker) margin call orders in the market which have met
|
||||
the requirements that to be matched (able to be margin called), they always
|
||||
take precedence over the (maker) limit orders on the same side, no matter
|
||||
whether the limit orders provided better price.
|
||||
|
||||
For example, if trader A's margin call order is selling 100 BTS at no less than
|
||||
0.1 USD per BTS, trader B has a limit order selling 100 BTS at 0.09 USD per BTS,
|
||||
which means B's limit order has a better price for the opposite side to buy.
|
||||
Now if trader C placed an order that buys 10 BTS at 0.105 USD per BTS, A's
|
||||
margin call order will take precedence, B's limit order won't be matched. That
|
||||
means C is forced to "buy high" when have chance to "buy low", which is
|
||||
unexpected.
|
||||
|
||||
Users have been confused by this behavior, as discussed in [bitshares-core
|
||||
issue #625](https://github.com/bitshares/bitshares-core/issues/625) and other
|
||||
threads.
|
||||
|
||||
Another scenario is described in [Bitshares-core
|
||||
issue #453](https://github.com/bitshares/bitshares-core/issues/453)
|
||||
that sometimes a taker margin call order may be matched with a maker limit order
|
||||
which is not on the top of the order book. This can be seen as a bug.
|
||||
|
||||
# Rationale
|
||||
|
||||
Always matching taker order (e.g. a buy) with a maker order which offered best
|
||||
price (aka lowest ask), is a simpler rule which most users would understand
|
||||
easily.
|
||||
|
||||
There is a parameter in price feed named MSSR, which stands for "maximum short
|
||||
squeeze ratio". Maker price of margin call orders is MSSP, which stands for
|
||||
"maximum short squeeze price", is calculated as `feed_price / MSSR`.
|
||||
Note: `feed_price` here is in terms of debt/collateral, aka "how much debt per
|
||||
collateral".
|
||||
|
||||
That said, the price that margin call orders are offering is MSSP. The prices
|
||||
those limit orders are offering are the limit prices.
|
||||
|
||||
When placing a limit (e.g. buy) order with a price beyond the lowest sell,
|
||||
the order is expected to "walk the book", matching each order on the opposite
|
||||
side in turn, at that order's price, until the new limit order is completely
|
||||
filled, or there is no more sell order matching its price.
|
||||
|
||||
To meet the expectation,
|
||||
* firstly, we need to match the limit buy order with the limit sell orders
|
||||
whose prices are lower than MSSP and prices can match the new order;
|
||||
* then, if the new limit buy order hasn't been completely filled, match it with
|
||||
the margin calls if MSSP can match the new order's price;
|
||||
* then, if the new limit buy order still hasn't been completely filled, match it
|
||||
with the rest sell orders until it's completely filled or no more sell order
|
||||
matching its price
|
||||
|
||||
|
||||
# Specifications
|
||||
|
||||
## Matching a taker limit order
|
||||
|
||||
New limit order is being processed in `apply_order(...)` function of `database`
|
||||
class.
|
||||
|
||||
Currently, in the function, firstly call orders will be checked and matched.
|
||||
After that, limit orders on the opposite side will be checked and matched.
|
||||
|
||||
Need to change the logic to:
|
||||
1. firstly, sort the limit orders on the opposite by `price`, best price first,
|
||||
end at MSSP; check them one by one, calls `match(...)` function until the
|
||||
return value is not `2` which means the new order is completely filled;
|
||||
2. if reach the end (MSSP), which means the new order is still unfilled,
|
||||
call `check_call_orders(..)` function or an equivalent;
|
||||
3. check if `new_order_object` still exist, if yes, redo step one but set the
|
||||
maximum possible price of the market as end price.
|
||||
|
||||
## Matching taker margin call orders
|
||||
|
||||
For [bitshares-core
|
||||
issue #453](https://github.com/bitshares/bitshares-core/issues/453),
|
||||
in `check_call_orders(...)` function of `database` class,
|
||||
iterator `limit_itr` will move forward when variable `filled_limit` is `true`.
|
||||
`filled_limit` will be set to `true` when a limit order get completely filled.
|
||||
However, since `filled_limit` is declared out of the `while` block,
|
||||
it doesn't get reset to `false` after `limit_itr` moved forward. That means
|
||||
after the first limit order get completedly filled, `filled_limit` will always
|
||||
be `true`, so `limit_itr` will always move forward no matter whether *current*
|
||||
limit order got completedly filled, so a taker call order may match
|
||||
with a limit order that is not on the top of the order book.
|
||||
|
||||
To fix this, need to change the code to make sure `limit_itr` always references
|
||||
the limit order on the top of the order book when dereferencing.
|
||||
|
||||
# Discussion
|
||||
|
||||
[to be added if any]
|
||||
|
||||
# Summary for Shareholders
|
||||
|
||||
[to be added if any]
|
||||
|
||||
# Copyright
|
||||
|
||||
This document is placed in the public domain.
|
||||
|
||||
# See Also
|
||||
|
||||
* https://github.com/bitshares/bitshares-core/issues/625
|
||||
* https://github.com/bitshares/bitshares-core/issues/453
|
||||
* https://bitsharestalk.org/index.php?topic=25926.0
|
104
bsip-0034.md
Normal file
104
bsip-0034.md
Normal file
|
@ -0,0 +1,104 @@
|
|||
BSIP: 0034
|
||||
Title: Always Trigger Margin Call When Call Price Above Or At Price Feed
|
||||
Author: Abit More <https://github.com/abitmore>
|
||||
Status: Accepted
|
||||
Type: Protocol
|
||||
Created: 2018-02-18
|
||||
Discussion: https://github.com/bitshares/bitshares-core/issues/606
|
||||
Replaces: -
|
||||
Worker: 1.14.95
|
||||
|
||||
# Abstract
|
||||
|
||||
Currently, in BitShares, a short position may be margin called only when both
|
||||
two requirements are met:
|
||||
* call price is above or equal to median price feed
|
||||
* no limit order on the book is buying collateral with price higher than the
|
||||
short position's call price
|
||||
|
||||
This behavior has led to certain confusion and anger among market participants.
|
||||
|
||||
This BSIP proposes a new behavior to improve the situation: drop the second
|
||||
requirement, trigger margin call when the first requirement is met.
|
||||
|
||||
# Motivation
|
||||
|
||||
To avoid ambiguity, in this article, all prices are in terms of
|
||||
`debt asset / collateral asset`, aka how much debt asset per collateral
|
||||
asset. A bid is an order to buy collateral asset with debt asset.
|
||||
|
||||
Generally, a short position may be margin called when its collateral ratio is
|
||||
below or equal to maintenance collateral ratio (MCR).
|
||||
|
||||
However, to calculate collateral ratio, a fair collateral price is needed.
|
||||
|
||||
In BitShares, there are two data sources can be used to decide the fair
|
||||
collateral price:
|
||||
* the internal market
|
||||
* the price feeds
|
||||
|
||||
Currently, both data sources are used. Specifically, collateral price is decided
|
||||
as the higher one between the highest bid price on the internal market and the
|
||||
median price feed. That said, when a short position's collateral ratio has
|
||||
fallen to below or equal to MCR according to median price feed (in this case,
|
||||
call price of the short position is above or equal to median price feed), if
|
||||
there is a bid on the market with high price, the short position won't be margin
|
||||
called.
|
||||
|
||||
This mechanism has led to certain confusion and anger among market participants.
|
||||
* there are often orders with overlapping price on the book but didn't fill
|
||||
* there are often short positions selling collaterals with low prices, but
|
||||
traders are unable to buy at those prices
|
||||
* it often causes borrowers to sell collaterals at a low price when have chances
|
||||
to sell at higher price
|
||||
* market manipulators / arbitrage traders have more chances to force borrowers
|
||||
to sell collaterals at lower price
|
||||
|
||||
This BSIP effectively proposes a new behavior: derive the fair collateral price
|
||||
only from price feeds.
|
||||
|
||||
# Rationale
|
||||
|
||||
Since price feeds are provided by a set of chosen producers, the median price
|
||||
feed is usually considered trustworthy. On the other hand, instant market
|
||||
price is not as reliable, especially for the markets with poor depth, so it's
|
||||
a rather limited supplement for calculating collateral price.
|
||||
|
||||
At this moment, changing the rule to only use median price feed will clear away
|
||||
the confusion the end users may have, while still keeping the derived collateral
|
||||
price fair to an extent.
|
||||
|
||||
After this change is done, placing a new limit order will no longer trigger a
|
||||
margin call, cancelling a limit order or expiring a limit order will no longer
|
||||
trigger a margin call as well, that means we don't need to check for new margin
|
||||
calls nor black swan events in those scenarios, so we'll gain a side benefit on
|
||||
performance.
|
||||
|
||||
# Specifications
|
||||
|
||||
In `check_call_orders(...)` function of `database` class, when matching a call
|
||||
order with a limit order, there is a check:
|
||||
`if( match_price > ~call_itr->call_price )`, when the result is `true`,
|
||||
processing will be ended and `margin_called` will be returned.
|
||||
Need to skip the check and the following `return` action.
|
||||
|
||||
In `do_apply(...)` function of `limit_order_cancel_evaluator` class, and
|
||||
similar code blocks after a limit order object is removed, no longer need to
|
||||
call `check_call_orders(...)` function of `database` class.
|
||||
|
||||
# Discussion
|
||||
|
||||
[to be added if any]
|
||||
|
||||
# Summary for Shareholders
|
||||
|
||||
[to be added if any]
|
||||
|
||||
# Copyright
|
||||
|
||||
This document is placed in the public domain.
|
||||
|
||||
# See Also
|
||||
|
||||
* https://github.com/bitshares/bitshares-core/issues/606
|
||||
* https://bitsharestalk.org/index.php?topic=25926.0
|
488
bsip-0035.md
Normal file
488
bsip-0035.md
Normal file
|
@ -0,0 +1,488 @@
|
|||
BSIP: 0035
|
||||
Title: Mitigate Rounding Issue On Order Matching
|
||||
Author: Abit More <https://github.com/abitmore>
|
||||
Status: Accepted
|
||||
Type: Protocol
|
||||
Created: 2018-02-19
|
||||
Discussion: https://github.com/bitshares/bitshares-core/issues/132,
|
||||
https://github.com/bitshares/bitshares-core/issues/184,
|
||||
https://github.com/bitshares/bitshares-core/issues/342
|
||||
Replaces: -
|
||||
Worker: 1.14.96
|
||||
|
||||
# Abstract
|
||||
|
||||
Under some circumstances, when two orders get matched, due to rounding,
|
||||
one order may be paying more than enough, even paying something but receiving
|
||||
nothing. This looks unfair.
|
||||
|
||||
This BSIP proposes an overall mechanism to mitigate rounding issue when matching
|
||||
orders and avoid something-for-nothing issue completely.
|
||||
|
||||
This BSIP also sets two principles for order matching:
|
||||
* never pay more than enough, and
|
||||
* something-for-nothing shouldn't happen.
|
||||
|
||||
# Motivation
|
||||
|
||||
There are mechanisms in the system to try to avoid something-for-nothing issue,
|
||||
however, not all scenarios are well-handled, see [bitshares-core
|
||||
issue #184](https://github.com/bitshares/bitshares-core/issues/184) for example.
|
||||
|
||||
Other than that, rounding issue occurs frequently and has led to a lot of
|
||||
confusion among market participants, see [bitshares-core
|
||||
issue #342](https://github.com/bitshares/bitshares-core/issues/342) for example.
|
||||
|
||||
# Rationale
|
||||
|
||||
## Amounts, Prices and Rounding
|
||||
|
||||
Amounts in the system are integers with per-asset fixed precisions.
|
||||
The minimum positive amount of an asset is called one Satoshi.
|
||||
|
||||
Prices in the system are rational numbers, which are expressed as
|
||||
`base_amount / quote_amount` (precisions are omitted here).
|
||||
|
||||
To calculate how much amount of asset B is equivalent to some amount of
|
||||
asset A, need to calculate `amount_of_a * a_to_b_price` which is
|
||||
`amount_of_a * b_amount_in_price / a_amount_in_price`. The accurate result
|
||||
of this formula is a rational number. To convert it to the final result which
|
||||
is an amount, which is an integer, may need to round.
|
||||
|
||||
## Order Matching
|
||||
|
||||
An order means someone is willing to give out some amount of asset X expecting
|
||||
to get some amount of asset Y. The ratio between the two assets is the price of
|
||||
the order. The price can be expressed as either `x_amount / y_amount` or
|
||||
`y_amount / x_amount`, when we know which amount in the price is of which asset,
|
||||
the two expressions are equivalent. The amount of asset X is known and fixed.
|
||||
|
||||
In a market, E.G. the X:Y market, some people are selling X for Y, some people
|
||||
are selling Y for X (or say buying X with Y). Orders are classified by type
|
||||
(buy or sell), then ordered by price. For each type, the order offering the
|
||||
best price is on the top. So, in every market there may be a top buy order and
|
||||
a top sell order, name them highest bid and lowest ask, so there is
|
||||
a highest bid price (in terms of `asset X amount / asset Y amount`),
|
||||
and a lowest ask price (in terms of `asset X amount / asset Y amount` as well).
|
||||
|
||||
When the highest bid price is higher or equal to the lowest ask price, the two
|
||||
top orders can be matched with each other.
|
||||
|
||||
## The Match Price
|
||||
|
||||
In a continuous trading market, orders are placed one by one, when comparing
|
||||
every two orders, it's deterministic that one order is placed earlier than the
|
||||
other.
|
||||
|
||||
In BitShares, it doesn't mean that the transaction that contains the first
|
||||
order is signed before the transaction contains the second, but means that
|
||||
the first order is processed earlier than the second in the witness node that
|
||||
produced the block that contains the second order.
|
||||
|
||||
When two orders get matched, the one placed earlier is maker, the other one
|
||||
is taker. Say, the maker provides an offer, the taker accept the offer.
|
||||
So, when calculating who will get how much, we use the maker order's price,
|
||||
aka maker price, as the match price.
|
||||
|
||||
## The Need for Compromise
|
||||
|
||||
When matching two orders, due to rounding, usually we're unable to completely
|
||||
satisfy both parties.
|
||||
|
||||
Here is an example mentioned in the 4th comment of [bitshares-core
|
||||
issue #132](https://github.com/bitshares/bitshares-core/issues/132):
|
||||
|
||||
Alice's order: Sell CORE at $3 / 8, balance 1000000 CORE
|
||||
Bob's order: Buy CORE at $19 / 50, balance $10
|
||||
|
||||
Both assets have precision of 1, i.e. the order balances are
|
||||
1000000 CORE-satoshis and 10 USD-satoshis repectively.
|
||||
|
||||
Alice is selling at $3/8 CORE = $0.375 / CORE and Bob is buying at
|
||||
$19 / 50 CORE = $0.38, so based on the price, Alice and Bob should match.
|
||||
|
||||
Bob's $10 / $0.38 ~ 26.3. So 26.3 is the fewest CORE he is willing to accept
|
||||
(assuming that the meaning of "price" is "the least favorable exchange rate
|
||||
a party is willing to accept in trade"). Combined with the design restriction
|
||||
that satoshis are indivisible, in practice this means Bob will only accept 27
|
||||
or more CORE for his $10.
|
||||
|
||||
But $10 / 27 gives a price smaller than $0.370 and $0.371, which is smaller
|
||||
than Alice's sale price of $0.375. So neither party can fill this offer.
|
||||
|
||||
We need to come to a compromise.
|
||||
|
||||
## The Possible Solutions
|
||||
|
||||
There are some possible solutions listed in the 5th comment of [bitshares-core
|
||||
issue #132](https://github.com/bitshares/bitshares-core/issues/132):
|
||||
|
||||
- (a) Fill someone at a less favorable exchange rate than the price they
|
||||
specified in their order. Downside: This violates the above definition of
|
||||
price; i.e. if a user enters a price intending the system to never sell below
|
||||
that price in any circumstance, the system will not always behave in a way
|
||||
which fulfills that user intent.
|
||||
|
||||
- (b) Keep both orders on the books. Downside: This complicates the matching
|
||||
algorithm, as now Alice might be able to match an order behind Bob's order.
|
||||
Naive implementation would have potentially unbounded matching complexity;
|
||||
a more clever implementation might be possible but would require substantial
|
||||
design and testing effort.
|
||||
|
||||
- (c) Cancel an order. This is complicated by the fact that an order such as
|
||||
a margin call cannot be cancelled. Downside: When there are margin calls
|
||||
happening, it seems perverse to delete a large order that's willing to fill
|
||||
them just because the lead margin call happens to fall in a narrow window
|
||||
which causes a rounding issue. Also, orders cancelled by this mechanism
|
||||
cannot be refunded. Otherwise an attacker who wants to consume
|
||||
a lot of memory on all nodes could create a large number of orders, then
|
||||
trigger this case to cancel them all, getting their investment in deferred
|
||||
cancellation fees back without paying the cancel op's per-order fee as
|
||||
intended.
|
||||
|
||||
- (d) Require all orders to use the same denominator. Altcoin exchanges and
|
||||
many real-world markets like the stock market solve this problem by specifying
|
||||
one asset as the denominator asset, specifying a "tick" which is the smallest
|
||||
unit of price precision, and requiring all prices to conform.
|
||||
Downside: Complicates the implementation of flipped market UI, may require
|
||||
re-working part of market GUI, reduces user flexibility, new asset fields
|
||||
required to specify precision, if `n` assets exist then `O(n^2)` markets
|
||||
could exist and we need to figure out how to determine the precision
|
||||
requirement for all of them.
|
||||
|
||||
## The Chosen Solution
|
||||
|
||||
Current code actually implemented (a) in the first place: when matching two
|
||||
orders, if there is a rounding issue, the order with smaller volume will be
|
||||
filled at a less favorable price. It's the least bad compromise since it has
|
||||
the most efficiency (highest traded volume while not hard to implement) among
|
||||
the solutions.
|
||||
|
||||
The algorithm can be described as follows (sample code is
|
||||
[here](https://github.com/bitshares/bitshares-core/blob/2.0.171105a/libraries/chain/db_market.cpp#L311-L324)):
|
||||
|
||||
Assuming the maker order is selling amount `X` of asset A, with price
|
||||
`maker_price = maker_b_amount / maker_a_amount`; assuming the taker is buying
|
||||
asset A with amount `Y` of asset B, with price
|
||||
`taker_price = taker_b_amount / taker_a_amount`. Anyway, since the two orders
|
||||
will be matched at maker price, the taker price doesn't matter here as long
|
||||
as it's higher than or equal to maker price. Note: currently all limit orders
|
||||
are implemented as sell limit orders, so in the example, the taker order can
|
||||
only specify amount of asset B but not amount of asset A.
|
||||
|
||||
Now compare `X * maker_price` with `Y`. To be accurate (avoid rounding),
|
||||
compare `X' = X * maker_b_amount` with `Y' = Y * maker_a_amount`.
|
||||
* The best scenario is when `X' == Y'`, which means both orders can be
|
||||
completely filled at `maker_price`.
|
||||
* If `X' < Y'`, it means the maker order can be completely filled but the
|
||||
taker order can't, aka the maker order is smaller.
|
||||
In this case, maker pay amount `X` of asset A to taker, taker pay amount
|
||||
`Y" = round_down( X' / maker_a_amount )` of asset B to maker.
|
||||
Note: due to rounded down, it's possible that `Y"` is smaller than the
|
||||
rational number
|
||||
`X * maker_price`, which means `Y" / X` may be lower than `maker_price`,
|
||||
that said, the maker order may has been filled at a less favorable price.
|
||||
* If `X' > Y'`, it means the taker order can be completely filled but the
|
||||
maker order can't, aka the taker order is smaller.
|
||||
In this case, taker pay amount `Y` of asset B to maker, maker pay amount
|
||||
`X" = round_down( Y' / maker_b_amount )` of asset A to taker.
|
||||
Note: due to rounded down, it's possible that `X"` is smaller than the
|
||||
rational number
|
||||
`Y / taker_price`, which means `Y / X"` may be higher than `taker_price`,
|
||||
that said, the taker order may has been filled at a less favorable price.
|
||||
|
||||
## Issues With The Chosen Solution
|
||||
|
||||
### The Something-for-nothing Issue
|
||||
|
||||
When filling a small order at a less favorable price, the receiving
|
||||
amount is often rounded down to zero, thus causes the something-for-nothing
|
||||
issue. Current code tried to solve the issue by cancelling the smaller order
|
||||
when it would receive nothing, but only applied this rule in a few senarios
|
||||
(the processed parties won't be paying something for nothing):
|
||||
* when matching two limit orders, processed the maker
|
||||
* when matching a limit order with a call order, processed the call order
|
||||
* when matching a settle order with a call order, processed the call order
|
||||
* when globally settling, processed the call order
|
||||
|
||||
Other senarios that need to be processed as well (these to-be-processed parties
|
||||
may be paying something for nothing in current system):
|
||||
* when matching two limit orders, process the taker
|
||||
* when matching a limit order with a call order, process the limit order
|
||||
* when matching a force settle order with a call order, process the settle order
|
||||
* when globally settling, process the settlement fund
|
||||
* when force settling after an asset has been globally settled, paying the force
|
||||
settle order from global settlement fund, process the settle order
|
||||
|
||||
### The Broader Rounding Issue
|
||||
|
||||
Something-for-nothing is only a subset of rounding issues, it's the most extreme
|
||||
one. There are much more scenarios that one of the matched parties would be
|
||||
paying more than enough, although they're not paying something for nothing
|
||||
overall. Some scenarios are discussed in [bitshares-core
|
||||
issue #342](https://github.com/bitshares/bitshares-core/issues/342).
|
||||
|
||||
Take a scenario similar to the one described in the 4th comment of
|
||||
[bitshare-core
|
||||
issue #132](https://github.com/bitshares/bitshares-core/issues/132) as an
|
||||
example:
|
||||
* Alice's order: Sell CORE at `$3 / 80 = $0.0375`, balance `50 CORE`
|
||||
* Bob's order: Buy CORE at `$19 / 500 = $0.038`, balance `$100`
|
||||
|
||||
Current system would process them as follows:
|
||||
* If Alice's order is maker, use `$3 / 80` as match price; since Alice's order
|
||||
is smaller, round in favor of Bob's order, so Alice will pay the whole `50
|
||||
CORE` and get `round_down(50 CORE * $3 / 80 CORE) = round_down($1.6) = $1`,
|
||||
the effective price would be `$1 / 50 = $0.02`;
|
||||
* If Bob's order is maker, use `$19 / 500` as match price; since Alice's order
|
||||
is smaller, round in favor of Bob's order, so Alice will pay the whole `50
|
||||
CORE` and get `round_down(50 CORE * $19 / 500 CORE = round_down($1.9) = $1`,
|
||||
the effective price would still be `$1 / 50 = $0.02`.
|
||||
|
||||
Both results are far from Alice's desired price `$0.0375`. Actually, according
|
||||
to Bob's desired price, paying `round_up($1 * 500 CORE / $19) = 27 CORE` would
|
||||
be enough, then the effective price would be `$1 / 27 = $0.037`, which is
|
||||
still below Alice's desired price `$0.0375`, but much closer than `$0.02`.
|
||||
|
||||
## The Improved Solution Proposed By This BSIP
|
||||
|
||||
The detailed rules proposed by this BSIP with new rules highlighted:
|
||||
|
||||
* match in favor of taker, or say, match at maker price;
|
||||
|
||||
* round the receiving amounts according to rules below.
|
||||
|
||||
* When matching two limit orders, round down the receiving amount of the
|
||||
smaller order,
|
||||
* **if the smaller order would get nothing, cancel it;**
|
||||
* **otherwise, calculate the amount that the smaller order would pay as
|
||||
`round_up(receiving_amount * match_price)`.**
|
||||
* **After filled both orders, for each remaining order (with a positive
|
||||
amount remaining), check the remaining amount, if the amount is too small
|
||||
so the order would receive nothing on next match, cancel the order.**
|
||||
|
||||
* When matching a limit order with a call order,
|
||||
* **if the call order is receiving the whole debt amount, which means it's
|
||||
smaller and the short position will be closed after the match, round up its
|
||||
paying amount; otherwise,** round down its paying amount.
|
||||
* **In the latter case,**
|
||||
* **if the limit order would receive nothing, cancel it (it's smaller,
|
||||
so safe to cancel);**
|
||||
* **otherwise, calculate the amount that the limit order would pay as
|
||||
`round_up(receiving_amount * match_price)`. After filled both orders,
|
||||
if the limit order still exists, the remaining amount might be too small,
|
||||
so cancel it.**
|
||||
|
||||
* When matching a settle order with a call order,
|
||||
* **if the call order is receiving the whole debt amount, which means it's
|
||||
smaller and the short position will be closed after the match, round up its
|
||||
paying amount; otherwise,** round down its paying amount.
|
||||
* **In the latter case,**
|
||||
* **if the settle order would receive nothing,**
|
||||
* **if the settle order would be completely filled, cancel it;**
|
||||
* **otherwise, it means both orders won't be completely filled, which
|
||||
may due to hitting `maximum_force_settlement_volume`, in this case,
|
||||
don't fill any of the two orders, and stop matching for this asset at
|
||||
this block;**
|
||||
* **otherwise (if the settle order would not receive nothing), calculate
|
||||
the amount that the settle order would pay as
|
||||
`round_up(receiving_amount * match_price)`. After filled both orders,
|
||||
if the settle order still exists,
|
||||
match the settle order with the call order again. In the new match, either
|
||||
the settle order will be cancelled due to too small, or we will stop
|
||||
matching due to hitting `maximum_force_settlement_volume`.**
|
||||
* **That said, only round up the collateral amount paid by the call order
|
||||
when it is completely filled, so if the call order still exist after the
|
||||
match, its collateral ratio won't be lower than before, which means we won't
|
||||
trigger a black swan event, nor need to check whether a black swan event
|
||||
would be triggered.**
|
||||
|
||||
* When globally settling, **in favor of global settlement fund, round up
|
||||
collateral amount.**
|
||||
|
||||
* When paying a settle order from global settlement fund, for predition
|
||||
markets, there would be no rounding issue, also no need to deal with
|
||||
something-for-nothing issue; for other assets, apply rules below:
|
||||
* if the settling amount is equal to total supply of that asset, pay the
|
||||
whole remaining settlement fund to the settle order;
|
||||
* otherwise, in favor of global settlement fund since its volume is bigger,
|
||||
round down collateral amount. **If the settle order would receive nothing,
|
||||
raise an exception (aka let the operation fail). Otherwise, calculate the
|
||||
amount that the settle order would pay as
|
||||
`round_up(receiving_amount * match_price)`; after filled the order, if there
|
||||
is still some amount remaining in the order, return it to the owner.**
|
||||
|
||||
## Examples Of The Improved Solution
|
||||
|
||||
### Example 1
|
||||
|
||||
Take the example mentioned in the 4th comment of [bitshares-core
|
||||
issue #132](https://github.com/bitshares/bitshares-core/issues/132):
|
||||
* Alice's order: Sell CORE at `$3 / 8 = $0.375`, balance `1000000 CORE`
|
||||
* Bob's order: Buy CORE at `$19 / 50 = $0.38`, balance `$10`
|
||||
|
||||
Process:
|
||||
* If both orders are limit orders
|
||||
* If Alice's order is maker, use `$3 / 8` as match price;
|
||||
since Bob's order is smaller, round in favor of Alice's order,
|
||||
so Bob will get
|
||||
`round_down($10 * 8 CORE / $3) = round_down(26.67 CORE) = 26 CORE`,
|
||||
and Alice will get
|
||||
`round_up(26 CORE * $3 / 8 CORE) = round_up($9.75) = $10`,
|
||||
the effective price would be `$10 / 26 CORE = $0.3846`.
|
||||
* If Bob's order is maker, use `$19 / 50` as match price; since Bob's
|
||||
order is smaller, round in favor of Alice's order, so Bob will get
|
||||
`round_down($10 * 50 CORE / $19 = round_down(26.32 CORE) = 26 CORE`,
|
||||
and Alice will get
|
||||
`round_up(26 CORE * $19 / 50 CORE) = round_up($9.88) = $10`,
|
||||
the effective price would still be `$10 / 26 CORE = $0.3846`.
|
||||
* If Alice's order is a call order, since it's bigger, round in favor of it,
|
||||
we will get same results.
|
||||
|
||||
### Example 2
|
||||
|
||||
If we change the example to this:
|
||||
* Alice's order: Buy CORE at `3 CORE / $8 = 0.375`, balance `$1000000`
|
||||
* Bob's order: Sell CORE at `19 CORE / $50 = 0.38`, balance `10 CORE`
|
||||
|
||||
Process:
|
||||
* If both orders are limit orders, we get similar results as above.
|
||||
* If Bob's order is a call order, it should have a debt amount which is an
|
||||
integer, for example `$26`, then
|
||||
* Alice would get
|
||||
* `round_up(26 * 3 / 8) = round_up(9.75) = 10 CORE` as a maker, or
|
||||
* `round_up(26 * 19 / 50) = round_up(9.88) = 10 CORE` as a taker.
|
||||
* Bob would get the full debt amount which is `$26`.
|
||||
* If Bob's order is a call order, but the debt amount is a bit high,
|
||||
for example `$27`, then Alice would get
|
||||
* `round_up(27 * 3 / 8) = round_up(10.125) = 11 CORE` as a maker, or
|
||||
* `round_up(27 * 19 / 50) = round_up(10.26) = 11 CORE` as a taker.
|
||||
|
||||
However, since the collateral is only `10 CORE`, this match will fail and
|
||||
trigger a black swan event.
|
||||
|
||||
### Example 3
|
||||
|
||||
If we change the example to that one used above:
|
||||
* Alice's order: Sell CORE at `$3 / 80 = $0.0375`, balance `50 CORE`
|
||||
* Bob's order: Buy CORE at `$19 / 500 = $0.038`, balance `$100`
|
||||
|
||||
Assuming both orders are limit orders, they'll be processed as follows:
|
||||
* If Alice's order is maker, use `$3 / 80` as match price; since Alice's order
|
||||
is smaller, round in favor of Bob's order, so Alice will get
|
||||
`round_down(50 CORE * $3 / 80 CORE) = round_down($1.6) = $1`,
|
||||
and Bob will get `round_up($1 * 80 CORE / $3) = round_up($26.67) = $27`,
|
||||
the effective price would be `$1 / 27 = $0.037`;
|
||||
* If Bob's order is maker, use `$19 / 500` as match price; since Alice's order
|
||||
is smaller, round in favor of Bob's order, so Alice will get
|
||||
`round_down(50 CORE * $19 / 500 CORE = round_down($1.9) = $1`,
|
||||
and Bob will get `round_up($1 * 500 CORE / $19) = round_up($26.3) = $27`,
|
||||
the effective price would also be `$1 / 27 = $0.037`.
|
||||
|
||||
# Specifications
|
||||
|
||||
## When Matching Two Limit Orders
|
||||
|
||||
### Handling Something-For-Nothing Issue
|
||||
|
||||
In `match( const limit_order_object&, OrderType ... )` function of `database`
|
||||
class, after calculated `usd_receives` which is for the taker,
|
||||
check if it is zero.
|
||||
If the answer is `true`, skip filling and see the order is filled, return `1`,
|
||||
so the order will be cancelled later.
|
||||
|
||||
### Handling Rounding Issue
|
||||
|
||||
In `match( const limit_order_object&, OrderType ... )` function of `database`
|
||||
class, after calculated `receives` for the smaller order, if it isn't zero,
|
||||
calculate `pays` for it as `round_up(receives * match_price)`.
|
||||
|
||||
If the smaller order is taker, after filled, even if there is still some amount
|
||||
remaining in the order, see it as completely filled and set the lowest bit of
|
||||
return value to `1`.
|
||||
|
||||
If the smaller order is maker, since it will be culled when filling,
|
||||
no need to change the logic.
|
||||
|
||||
## When Matching A Limit Order With A Call Order
|
||||
|
||||
In `check_call_orders(...)` function of `database` class,
|
||||
if the call order is smaller, round up `order_receives`,
|
||||
otherwise round down `order_receives`.
|
||||
|
||||
In the latter case,
|
||||
* if `order_receives` is zero, skip filling and cancel the limit order.
|
||||
* otherwise, calculate `order_pays` as
|
||||
`round_up(order_receives * match_price)`, then the limit order will be
|
||||
either completely filled, or culled due to too small after partially filled.
|
||||
|
||||
## When Matching A Settle Order With A Call Order
|
||||
|
||||
In `match( const call_order_object&, ... )` function of `database` class,
|
||||
if the call order is smaller, round up `call_pays`,
|
||||
otherwise round down `call_pays`.
|
||||
|
||||
In the latter case, check if `call_pays` is zero.
|
||||
* If the answer is `true`,
|
||||
* if `call_receives` is equal to `settle.balance`,
|
||||
call `cancel_order(...)` with parameter set to `settle`,
|
||||
then return a zero-amount collateral asset object;
|
||||
* otherwise, return a zero-amount collateral asset object directly.
|
||||
* Otherwise, calculate `call_receives` as `round_up(call_pays * match_price)`,
|
||||
then fill both orders normally. If the settle order still exists after the
|
||||
match, it will be processed again later but with different condition.
|
||||
|
||||
After returned, need to check the amount of returned asset at where calling the
|
||||
`match(...)` function, specifically, `clear_expired_orders()` function of
|
||||
`database` class. If the returned amount is `0`, break out of the `while` loop.
|
||||
If the settle order is still there and the returned amount is `0`,
|
||||
label that processing of this asset has completed. Also, in the outer loop,
|
||||
need to check the label, if found it's completed, process next asset.
|
||||
|
||||
## When Globally Settling
|
||||
|
||||
In `global_settle_asset(...)` function of `database` class, round up `pays`.
|
||||
|
||||
## When Paying A Settle Order From Global Settlement Fund
|
||||
|
||||
In `do_apply(...)` function of `asset_settle_evaluator` class,
|
||||
after calculated `settled_amount` and adjusted it according to the "total
|
||||
supply" rule, check if it's zero.
|
||||
|
||||
If the answer is `true`, and the asset is not a prediction market,
|
||||
throw a `fc::exception`.
|
||||
|
||||
If the answer is `false`, and the asset is not a prediction market,
|
||||
and `op.amount.amount` is not equal to `mia_dyn.current_supply`,
|
||||
calculate `pays` as `round_up(settled_amount * bitasset.settlement_price)`,
|
||||
then, only deduct `pays` from total supply, and refund
|
||||
`op.amount.amount - pays` to the user.
|
||||
|
||||
# Discussion
|
||||
|
||||
There is an argument suggests when matching call orders, we should always
|
||||
round in favour of the call. If a settlement receives 0 collateral as a result,
|
||||
that's acceptable, because the settlement price is unknown at the time when
|
||||
settlement is requested, so no guarantee is violated (within the range of
|
||||
rounding errors). This should keep the collateral > 0 as long as there is
|
||||
outstanding debt. A counter-argument supports rounding up to 1 Satoshi since
|
||||
rounding down to zero may break the promise of "every smart coin is backed
|
||||
by something".
|
||||
|
||||
There is an argument says breaking the `min_to_receive` limit is a no-go,
|
||||
because that's why it's called a "limit order". A counter-argument says
|
||||
slightly breaking the limit is the least bad compromise.
|
||||
|
||||
# Summary for Shareholders
|
||||
|
||||
[to be added if any]
|
||||
|
||||
# Copyright
|
||||
|
||||
This document is placed in the public domain.
|
||||
|
||||
# See Also
|
||||
|
||||
* https://github.com/bitshares/bitshares-core/issues/132
|
||||
* https://github.com/bitshares/bitshares-core/issues/184
|
||||
* https://github.com/bitshares/bitshares-core/issues/342
|
73
bsip-0036.md
Normal file
73
bsip-0036.md
Normal file
|
@ -0,0 +1,73 @@
|
|||
BSIP: 0036
|
||||
Title: Remove expired price feeds on maintenance interval
|
||||
Author: oxarbitrage <https://github.com/oxarbitrage>
|
||||
Status: Accepted
|
||||
Type: Protocol
|
||||
Created: 2018-02-22
|
||||
Discussion: https://bitsharestalk.org/index.php?topic=25996.0
|
||||
Replaces: -
|
||||
Worker: 1.14.97
|
||||
|
||||
# Abstract
|
||||
|
||||
Currently, expired bitasset feeds remain in the blockchain forever. The only way to get them erased is if operation `update_feed_producers` is called with new publishers on the asset. At this call, and only at this case, old publisher feeds will be deleted from the blockchain. If this operation never occurs or if it occurs maintaining some or all of the same publishers feeds will not be removed.
|
||||
|
||||
Some examples of this are the followings, where we can see feeds from 2015:
|
||||
|
||||
- http://open-explorer.io/#/objects/2.4.9 - HKD
|
||||
- http://open-explorer.io/#/objects/2.4.21 - USD
|
||||
- http://open-explorer.io/#/objects/2.4.10 - RUB
|
||||
- etc.
|
||||
|
||||
This BSIP proposes a protocol change to remove expired feeds at maintenance time.
|
||||
|
||||
# Motivation
|
||||
|
||||
Improve performance of the bitshares-core.
|
||||
|
||||
|
||||
# Rationale
|
||||
|
||||
The proposed change only affects the feed price when the feed expiration time is increased. This rarely happens, if ever, so in practice the effect on pricing is negligible. The savings in performance however, is not.
|
||||
|
||||
# Specifications
|
||||
|
||||
As mentioned in the abstract feeds stay in the blockchain forever unless `asset_update_feed_producers_evaluator::do_apply` is called.
|
||||
|
||||
The BSIP proposes to remove expired feeds at maintenance time by adding feed cleanup code at `db_main.cpp`.
|
||||
|
||||
Solution is not that simple, `asset_update_bitasset_operation` can change `feed_expiration_time` and `minimum_feeds` required for the asset.
|
||||
|
||||
If a feed is expired and the `feed_expiration_time` changes, expired feeds may became valid, similar if `minimum_feeds` (required to calculate the median) is increased, older feeds may became valid and used by the core market engine if available.
|
||||
|
||||
This scenario actually happened in the past and that is the reason the change will fail unless a hardfork protection is added.
|
||||
|
||||
## The proposed solution
|
||||
|
||||
Goal is to remove expired feeds in a safe manner. To do this we need to keep current behavior before hardfork date and only remove feeds at maintenance intervals after the hardfork. This will allow the chain to synchronize and start the cleanup at a point where all the feeds are valid, safely being able to remove them an continue clean from that time on.
|
||||
|
||||
This a permanent hardfork, code before hardfork date will work one way(current behavior) and after date new code will work different making the feed cleanup at maintenance times.
|
||||
|
||||
Feed cleanup code will only be executed after proposed hardfork date, at the first maintenance interval after date old feeds will be removed, node will not be able to use them anymore as they will not be available in the database.
|
||||
|
||||
If `asset_update_bitasset_operation` is called before hardfork operation will be normal as it is currently is now.
|
||||
|
||||
If `asset_update_bitasset_operation` is called after hardfork and increases the `minimum_feeds` while they are not enough feeds `update_median_feeds()` will set a null feed. This is current `asset_update_bitasset_operation`, no need to make any change in the operation.
|
||||
|
||||
|
||||
# Discussion
|
||||
|
||||
https://bitsharestalk.org/index.php?topic=25996.0
|
||||
|
||||
# Summary for Shareholders
|
||||
|
||||
[to be added if any]
|
||||
|
||||
# Copyright
|
||||
|
||||
This document is placed in the public domain.
|
||||
|
||||
# See Also
|
||||
|
||||
* https://github.com/bitshares/bitshares-core/issues/518
|
||||
* https://github.com/bitshares/bitshares-core/pull/598
|
64
bsip-0037.md
Normal file
64
bsip-0037.md
Normal file
|
@ -0,0 +1,64 @@
|
|||
BSIP: 0037
|
||||
Title: Allow new asset name to end with a number
|
||||
Author: oxarbitrage <https://github.com/oxarbitrage>
|
||||
Status: Accepted
|
||||
Type: Protocol
|
||||
Created: 2018-02-23
|
||||
Discussion: https://bitsharestalk.org/index.php?topic=25997.0
|
||||
Replaces: -
|
||||
Worker: 1.14.98
|
||||
|
||||
# Abstract
|
||||
|
||||
Currently, the bitshares-core do not allow asset creation that start or end with a numerical character. Creation of index style assets like `CRYPTO500` are not possible.
|
||||
|
||||
This BSIP proposes a protocol change to allow number characters at the end of the created asset name.
|
||||
|
||||
# Motivation
|
||||
|
||||
Economical, enable more asset names to be created in the exchange.
|
||||
|
||||
|
||||
# Rationale
|
||||
|
||||
No valid reason was found until now about why this is not allowed. The creation of index style assets will bring new business to the exchange.
|
||||
|
||||
# Specifications
|
||||
|
||||
Restriction in asset names are detailed in `asset_ops.cpp`:
|
||||
|
||||
```
|
||||
/**
|
||||
* Valid symbols can contain [A-Z0-9], and '.'
|
||||
* They must start with [A, Z]
|
||||
* They must end with [A, Z]
|
||||
* They can contain a maximum of one '.'
|
||||
*/
|
||||
```
|
||||
|
||||
BSIP proposes to change third rule to:
|
||||
|
||||
`They must end with [A, Z0-9]`
|
||||
|
||||
As file where the changes are needed(`asset_ops.cpp`) do not have access to the database, we are unable to use `head_block_time()` to create the hardfork guard.
|
||||
|
||||
The process is more complicated and it is described as follows:(quote from @abit in github ticker: https://github.com/bitshares/bitshares-core/issues/620#issuecomment-364803143):
|
||||
|
||||
"To make the change, need to loose the validation code in `asset_ops.cpp`, add a hard fork guard code with original rule to asset_evaluator to make sure no rule change before the hard fork, add corresponding hard fork guard code in proposal_evaluator. After hard fork, those hard fork guard code can be safely removed."
|
||||
|
||||
# Discussion
|
||||
|
||||
https://bitsharestalk.org/index.php?topic=25997.0
|
||||
|
||||
# Summary for Shareholders
|
||||
|
||||
[to be added if any]
|
||||
|
||||
# Copyright
|
||||
|
||||
This document is placed in the public domain.
|
||||
|
||||
# See Also
|
||||
|
||||
* https://github.com/bitshares/bitshares-core/issues/620
|
||||
* https://github.com/bitshares/bsips/issues/52
|
89
bsip-1200.md
Normal file
89
bsip-1200.md
Normal file
|
@ -0,0 +1,89 @@
|
|||
BSIP: 1200 (unassigned)
|
||||
Title: Stealth development, Phase II
|
||||
Authors: Christopher J. Sanborn <...>
|
||||
Agorise, Ltd. <Agorise@protonmail.ch>
|
||||
Status: Draft
|
||||
Type: Informational
|
||||
Created: 2018-01-29
|
||||
Discussion: <https://t.me/Agorise>
|
||||
|
||||
|
||||
## Abstract
|
||||
|
||||
To discuss the continued development of Stealth functionality and provide an overview of the following BSIPs which define components of that development.
|
||||
|
||||
Component BSIPs: _(Works in progress!!)_
|
||||
|
||||
Number | Title | Type | Status
|
||||
:-----------------:|--------------------------------------------------------------|---------------|--------
|
||||
[1200](bsip-1200.md) | Stealth development, Phase II — _(this document)_ | Informational | Draft
|
||||
[1201](bsip-1201.md) | New operations for Confidential Asset (CA) transactions | Protocol | Draft
|
||||
[1202](bsip-1202.md) | Ring signatures for untraceability of Stealth transactions | Protocol | Draft
|
||||
[1203](bsip-1203.md) | Blockchain scanning for inbound Stealth transactions | Protocol | Draft
|
||||
[1204](bsip-1204.md) | Deterministic addresses for Stealth wallets | Informational | Draft
|
||||
[1205](bsip-1205.md) | Metadata hiding via Garlic Routing and other means | Informational | Draft
|
||||
|
||||
## Motivation
|
||||
|
||||
The initial phase of Stealth development was proposed and implemented in [BSIP-0008](bsip-0008.md), and is live on the BitShares network. Support for this first round of confidentiality features has been implemented in the CLI wallet, and has also been demonstrated in the UI wallet by Agorise, Ltd., in a code fork not yet integrated into the mainline UI-Wallet code. Utilization of the privacy features remains low, for two reasons: (1) the difficulty of using the CLI wallet for day-to-day activities, and (2) the Stealth feature set thus far, while valuable, does not yet provide a comprehensive privacy solution.
|
||||
|
||||
Phase One of Stealth development consisted of the implementation of Confidential Transactions (CT) [[1]](#see-also), which was initially proposed for the Bitcoin network in a paper by Greg Maxwell. CT provides two key features: **value-blinding**, and **stealth addresses**. Value-blinding means that the value amounts of transactions are unknowable except to the parties of the transaction (provided the transaction is sufficiently removed from the operation that initially converted a public balance to a blind balance). Stealth addresses are an address format that the sender can use to derive a "shared secret" public key for which only the recipient can derive a private key, without revealing publicly that the stealth address and the public key used to transmit the funds are related. The use of stealth addresses helps to anonymize transactions, however it creates a burden of communication between the sender and the recipient, who must be made aware of the existence of an inbound transaction.
|
||||
|
||||
Stealth addresses also provide partial **unlinkability**, or the inability to "link" balance elements (we'll call them UTXOs for Unspent Transaction Outputs) together to see that they are controlled by the same party. However, wallet implementations may, in order to facilitate discovery by the receiving party, publicly embed the stealth address of the receiving party into the transaction, thus breaking unlinkability and threatening anonymity. Heretofore, no privacy-preserving method has been proposed on this network to enable discovery, other than the sender and receiver being in direct communication off of the blockchain (e.g. sending **transaction receipts**). Furthermore, CT transactions are **traceable**, meaning that a transaction reveals which UTXOs are consumed in the creation of new UTXOs. This has two implications: (1) a transaction history can be constructed, and it may be possible to establish a vary narrow set of originating users who initally "blinded" a previously public balance, thus potentially establishing to a high degree of probability *who* is involved and *how much* value is involved in a particular sequence of transactions, and (2) a user spending a balance consisting of more than one UTXO will of necessity reveal that those UTXOs are controlled by the same party, or "linked," thus again breaking unlinkability.
|
||||
|
||||
In what follows we propose methods of enhancing the confidential abilities offered by the BitShares network by integrating specific solutions to achieve unlinkability, untraceability, and automated transaction discovery by the receiving party. Additionally, since BitShares is a multi-asset blockchain, we propse to adopt Confidential Assets (CA). CA is an extension to CT that hides not just the values of a transaction, but also the assets involved. Further, we propose various convenience and user-experience enhancements to ease the backup burden placed on users and reduce the chances of lost funds. Lastly, we propose an ongoing effort to harden wallets and p2p nodes against metadata leaks.
|
||||
|
||||
## Rationale
|
||||
|
||||
We view "Stealth" as a constellation of features providing robust privacy and "grandma-friendly" usability and reliability. A user of Stealth transactions should be reasonably assured that their privacy is complete, and not underminable by easy-to-make procedural mistakes.
|
||||
|
||||
### "Blinded" vs. "Stealth"
|
||||
|
||||
To facilitate an orderly, confusion-free upgrade, and to differentiate between Phase One and Phase Two functionality, we have adopted the convention of referring to the existing CT transactions that only blind transaction amounts as **Blind Transfers**, and the proposed more fully-private transaction features as **Stealth Transfers**. The names convey that Stealth Transfers will be more private than Blind Transfers (although some user education will be needed on this). Upon maturity of the Stealth feature set, the utilization of Blind transfers should be retired.
|
||||
|
||||
### Specific features and enhancements
|
||||
|
||||
Specific features and enhancments proposed by this and associated BSIPs are as follows:
|
||||
|
||||
#### Asset Hiding
|
||||
|
||||
Confidential Assets (CA) [[2]](#see-also) extends Confidential Transactions (CT) to include asset hiding. Existing CT functionality can hide the value amount of a transaction, but the asset being transfered is publically visible in the transaction format. Since BitShares is a multi-asset blockchain, it would be of value to hide not just the value but also the identity of the asset involved. CA provides a method to do this. The proposal to implement CA on the BitShares network is in [BSIP-1201](bsip-1201.md).
|
||||
|
||||
#### Unlinkability and Untraceability
|
||||
|
||||
While BitShares is an account-based blockchain, similar e.g. to Ethereum and others, Stealth operations on the BitShares network follow a UTXO model, similar to BitCoin and related blockchains. UTXOs (Unspent Transaction Outputs) are discrete balances held in the "outputs" of transactions. A user's total balance is composed of the sum total of all UTXOs that fall under their control. A Stealth transaction consists of the destruction of one or more existing UTXOs and the creation of one or more new UTXOs. CT guarantees that the values of the outputs are unknowable (except for deductions that can be made if one happens to know, precisely or approximately, the values of the inputs). However, the current implementation of CT provides no privacy regarding *which* UTXOs are used as inputs to the transaction. Because of this, current CT transactions are fundamentally *traceable* and *linkable*. **Traceable** means that a history of prior inputs can be constructed, "tracing" where an output came from, and if the history is short enough (refering to how many prior UTXOs one must traverse before finding an operation where a public balance was converted to a blind balance) then it may be possible to reveal involved parties and estimate transaction values. **Linkability** refers to the ability to show that a set of UTXOs are controlled by the same party, or that a set of disparate transactions were conducted by the same party. Although the latter is well protected due to non-reuse of public keys, the former is implicated by CT. A CT transaction consuming multiple inputs necessarily reveals that all inputs are controlled by the same party, and if anonymity has been compromised for one input UTXO, then it is effectively compromised for all of them.
|
||||
|
||||
To solve the problems of linkability and traceability, we propose to take a page from the Monero project. The Monero network uses a system of **ring signatures** to create a high degree of plausible-deniability as regards who exectuted any particular transaction [[3]](#see-also). A ring signature is an *n* of *m* signature scheme wherein the set of inputs to a transaction is much larger than the set of inputs actually consumed by the transaction, and the signature provided guarantees that the correct party signed the transaction, but makes it impossible to know *which* party is the signer. With a Monero-like ring signature scheme, it is no longer possible to determine *which* UTXOs are "spent" vs. "unspent" (a mechanism to prevent double-spends does exist, of course). This means that it is no longer possible to construct an exclusive directed graph if inputs to outputs, thus providing untraceability and unlinkability. (More specifically, the set of inputs that *might* be in the history of a particular output rapidly becomes so large that it is no longer possible to say with significant probability that any particular party was involved.)
|
||||
|
||||
We propose and discuss the implementation of ring signatures for Stealth transactions in [BSIP-1202](bsip-1202.md).
|
||||
|
||||
#### Scanning for Inbound Stealth Transactions
|
||||
|
||||
The current implementation of CT requires that a sender must communicate to the recipient a "transaction receipt" that contains, in encrypted form, data that the recipient needs in order to take possession of a transaction output. This is burdensome, and implies a high risk of lost funds as a result of lost or uncommunicated receipts.
|
||||
|
||||
We propose automated, privacy-preserving methods of scanning for inbound transactions in [BSIP-1203](bsip-1203.md).
|
||||
|
||||
#### Backups of Stealth Balances
|
||||
|
||||
In [BSIP-1204](bsip-1204.md) we propose standardized derivation of Stealth addresses to enable backup seeds or brainkeys to be used to securely back up a Stealth account prior to first use, enabling recovery in the event of a lost or corrupted hot wallet.
|
||||
|
||||
#### Metadata Hiding
|
||||
|
||||
Lastly, in [BSIP-1205](bsip-1205.md), we propose methods of hardening wallets against eavesdropping and timing attacks, so that usage patterns and the method used to communicate with the peer-to-peer network do not compromise user privacy. (As an example, a naive wallet might check a users balance by querying the status of a set UTXOs under the user's control, revealing immediately to the network that a given set of UTXOs are "of interest" to a single party.)
|
||||
|
||||
## Specifications
|
||||
## Discussion
|
||||
## Summary for Shareholders
|
||||
## Copyright
|
||||
|
||||
This document is placed in the public domain.
|
||||
|
||||
## See Also
|
||||
|
||||
* Phase One of Stealth development: [BSIP-0008](bsip-0008.md)
|
||||
|
||||
[1] Confidential Transactions (Greg Maxwell) - https://people.xiph.org/~greg/confidential_values.txt
|
||||
|
||||
[2] Confidential Assets (Poelstra, et. al.) - https://blockstream.com/bitcoin17-final41.pdf
|
||||
|
||||
[3] Ring Confidential Transactions (Shen Noether) - https://eprint.iacr.org/2015/1098
|
106
bsip-1201.md
Normal file
106
bsip-1201.md
Normal file
|
@ -0,0 +1,106 @@
|
|||
BSIP: 1201 (unassigned)
|
||||
Title: New operations for Confidential Asset (CA) transactions
|
||||
Authors: Christopher J. Sanborn
|
||||
Status: Draft
|
||||
Type: Protocol
|
||||
Created: 2018-01-29
|
||||
Discussion: <url>
|
||||
|
||||
|
||||
## Abstract
|
||||
|
||||
Confidential Assets (CA) [[2]](#see-also) extends Confidential Transactions (CT) [[1]](#see-also) to include asset hiding. The BitShares network already understands and validates CT transactions, but is not yet capable of validating CA transactions. The transaction format will need minor to moderate updating and the validation routines will likewise need updating. We propose to either (a) update op-code 39, 49, and 41 to be CA capable, or (b) define new opcodes for CA stealth operations. The latter option probably affords a cleaner upgrade path. The old opcodes should then be disfavored for user wallet use.
|
||||
|
||||
Confidential Assets is a new, but not un-tested, technology. The Elements Project [[3]](#see-also) maintains an experimental implementation [[4]](#see-also) of CA as a Bitcoin side chain. The code for that project is MIT-licensed and can help guide the implementation of CA in the BitShares ecosystem.
|
||||
|
||||
_This BSIP is one of several describing_ [Stealth development, Phase II](bsip-1200.md).
|
||||
|
||||
## Motivation
|
||||
|
||||
A user maintains value-blinded balances on the BitShares blockchain as a collection of Pedersen commitments, which are EC curve points that obscure their committed values by adding a secret blinding factor times a generator point. By keeping the blinding factor secret, the user keeps their balance secret. Meanwhile, balances can be transferred, subdivided, or combined, provided the sum of blinding factors for all inputs to a transaction are equal to the sum of blinding factors of all outputs of a transaction. A user wishing to un-blind and "claim" a balance contained in a Pedersen commitment may do so by revealing the blinding factor for that commitment, which then allows the network to verify the committed amount and credit it to a public balance.
|
||||
|
||||
A commitment C is given mathematically by _C = value * H + blinding_factor * G_, where H and G are separate curve point generators with no known divisor between them. Because there is no known multiple _m_ solving _H = m*G_, the _value_ and _blinding_factor_ quantities are effectively independent, which makes _C_ a firm commitment to _value_.
|
||||
|
||||
BitShares is a multi-asset chain. The Pedersen commitments implemented in _Stealth Phase I_ commit only to a value amount, and nothing more. For the network to understand *which* asset is represented by a commitment, a plaintext metadata field is associated with the Graphene object for the commitment, containing the asset ID of the blinded asset. This means that the asset type of an individual blinded balance is publicly knowable.
|
||||
|
||||
Confidential Assets (CA) introduces a method for using a commitment to a hash of the asset description as a confounding factor similar to the blinding factor, such that, unless one already knows the asset represented by a particular Pedersen commitment, one cannot determine the asset from inspection alone. Furthermore, amounts of differing assets can be combined in a single transaction, so that the asset IDs of the outputs are not individually knowable. Thus, even by tracing the history of a given commitment, one cannot simply divine the asset type by back-tracing to the point where a public asset was blinded, as the history may implicate multiple asset types. When a user wishes to un-blind an asset, he may do so by providing both the value blinding factors and the asset blinding factors for the commitment, so that the network can confirm the contents thereof.
|
||||
|
||||
By allowing commitments of differing assets to be mixed together, we achieve two points for privacy: (1) we increase the available mix-in set for diffusion of transaction history, and (2) we make it more difficult for blockchain analysis to determine which assets are being operated on in any given transaction (the more assets involved in the history of a particular commitment, the greater the uncertainty of what the commitment contains).
|
||||
|
||||
## Rationale
|
||||
|
||||
### _Asset Tags_ and _Asset Commitments_
|
||||
|
||||
The existing value-blinded CT transaction capability includes an explicit **asset ID** in the transaction format, and unspent commitments are associated with an explicit clear-text asset ID in the database. For example, querying the blockchain for commitment "024449...8073" returns a structure containing three defining fields:
|
||||
|
||||
Field: | Data (Meaning)
|
||||
:----------:|----------
|
||||
commitment: | "0244492ceafc9c3d6fab34b4e2912b360a3276560651451580325f754705758073" |
|
||||
asset_id: | "1.3.0" (Core asset, BTS)
|
||||
owner: | (Authority struct specifying public key that must sign)
|
||||
|
||||
Under CA, the `asset_id` field would be replaced by `asset_commit` which is a commitment to an **asset tag**. The asset tag, denoted *H<sub>A</sub>*, is a curve point produced by a hashing procedure of some defining description of the asset (for example the `asset_id`, "1.3.0", etc.). The asset commitment, denoted *H*, is the sum of *H<sub>A</sub>* and a blind point, e.g., _H = H<sub>A</sub> + r*G_. Under this scheme, a CA commitment in the database would look similar to:
|
||||
|
||||
Field: | Data (Meaning)
|
||||
:------------:|----------
|
||||
commitment: | "0244492ceafc9c3d6fab34b4e2912b360a3276560651451580325f754705758073"
|
||||
asset_commit: | "022b607af588386028a97d6bc4be5caddb432340329bc808ba587c0b92ffb1087c"
|
||||
owner: | (Authority struct specifying public key that must sign)
|
||||
|
||||
As can be seen, casual inspection of the blockchain does not reveal the underlying asset, nor even asset tag, since it is commingled with a blinding factor. The only way to know the asset id would be if the commitment were a direct descendent of an asset-issuance transaction (where a public balance was blinded into a value-asset blind CA commitment). However, once a commitment is involved in a transaction involving inputs of multiple asset types, then uncertainty is introduced in the descendent commitments: the asset type will be _one_ of the parent asset types, but which one is unknowable except to parties that know the blinding factors.
|
||||
|
||||
_(TODO: QUESTION: How is it ensured that H<sub>A</sub> is a valid curve point? There must be some kind of nonce increment in the hash procedure to reject non-curve points. Find out.)_
|
||||
|
||||
### _Range Proofs_ and _Surjection Proofs_
|
||||
|
||||
Since the committed values in the Pedersen commitments are unknowable to parties not privy to the blinding factors, there exists the possibility for a transaction resulting in two or more outputs to encode a negative value in one output and an excess positive value in the others, resulting in inflated (i.e., counterfeit) asset supply. To prevent this, transactions with more than a single output are required to provide a **range proof** for each output, which is a zero-knowledge proof that the committed value is in a finite range between zero and an upper bound that won't risk overflow into negative values. (Values are encoded as 256-bit unsigned integers such that very-large integers "wrap around" and behave as negatives. Range proofs typically prove that a committed amount can be represented in 64-bits or less, affording no risk of overflow.) Under CA, the requirement to provide a range proof remains the same as under CT.
|
||||
|
||||
A new requirement in CA is the **asset surjection proof**. Similar to range proofs, ASPs prove that a validity contstraint is met on the blinded asset commitments of the transaction outputs. Specifically, it proves that the asset tags of the outputs match the asset tags of the inputs, without revealing what those tags are or which outputs correspond to which inputs. (TODO: preceding is imprecise.)
|
||||
|
||||
(TODO: discuss space requirments of ASPs, since they do add to transaction size. Compared to range proofs already included in CT transactions, however, they are comparatively small, except perhaps in the case of a large number of inputs and outputs in a single transaction.)
|
||||
|
||||
## Specifications
|
||||
|
||||
We propose to add the following three CA operations to the set of valid operations declared in graphene::chain::operation (chain/protocol/operations.hpp). The new CA operations are shown here side by side with their CT equivalents:
|
||||
|
||||
Op-Code | Description | Op-Code | Description
|
||||
:------:|-------------------------------|------------------|----------------------------------
|
||||
39 | transfer_to_blind_operation | 49 (placeholder) | transfer_to_ca_blind_operation
|
||||
40 | blind_transfer_operation | 50 (placeholder) | ca_blind_transfer_operation
|
||||
41 | transfer_from_blind_operation | 51 (placeholder) | transfer_from_ca_blind_operation
|
||||
| | | 52 (placeholder) | ct_to_ca_blind_transfer_operation
|
||||
|
||||
On the left are CT operations, whose outputs are value-blinded commitments. On the right are the corresponding CA operations, whose outputs are value-and-asset-blinded commitments. Of special note is op 52, which takes value-blinded CT inputs and outputs value-and-asset-blinded outputs. (As an alternative, op 50 could be made flexible enough to accept either CT or CA inputs, if this proves feasible.) As CA is seen as an upgrade to CT, no op-code is here proposed for transferring from CA back to CT, however in the event of market demand such an operation could be coded.
|
||||
|
||||
#### Proposed operation: transfer_to_ca_blind_operation (Public to Blind)
|
||||
|
||||
#### Proposed operation: ca_blind_transfer_operation (Blinded to Blind)
|
||||
|
||||
#### Proposed operation: transfer_from_ca_blind_operation (Blind to Public)
|
||||
|
||||
## Discussion
|
||||
|
||||
### Compatibility with ring-signature scheme
|
||||
|
||||
The Op-Code additions and specifications provided in this document do not conflict with or depend on the details of the ring-signature proposals in [BSIP-1202](bsip-1202.md), as they effect different substructures of the Transaction structure, and therefore both proposals can be implemented independently. This document specifies structures within the Operations vector within a Transaction structure, whereas the ring signature scheme would change the Signatures vector.
|
||||
|
||||
(TODO: Check whether preceding is true, i.e. that the operation structure is independent of signature method. If it is not true, include here a discussion of what else might need to be included in the structure, so that a decision can be made as to whether the two features would be best developed in parallel, or whether ring-sigs could be implemented subsequently as an "upgrade" to CA.)
|
||||
|
||||
#### Asset surjection and compatibility
|
||||
|
||||
TODO: Question: Are Asset-Surjection Proofs compatible with a Ring-Sig scheme? I.e., can a prover who is "accusing" unrelated inputs produce the proof even not knowing the blind factors and asset tags of the unrelated inputs?
|
||||
|
||||
## Summary for Shareholders
|
||||
## Copyright
|
||||
|
||||
This document is placed in the public domain.
|
||||
|
||||
## See Also
|
||||
|
||||
[1] Confidential Transactions (Greg Maxwell) - https://people.xiph.org/~greg/confidential_values.txt
|
||||
|
||||
[2] Confidential Assets (Poelstra, et. al.) - https://blockstream.com/bitcoin17-final41.pdf
|
||||
|
||||
[3] Elements Project - https://elementsproject.org
|
||||
|
||||
[4] Elements Project on GitHub - https://github.com/ElementsProject/elements
|
103
bsip-1202.md
Normal file
103
bsip-1202.md
Normal file
|
@ -0,0 +1,103 @@
|
|||
BSIP: 1202 (unassigned)
|
||||
Title: Ring signatures for untraceability of Stealth transactions
|
||||
Authors: Christopher J. Sanborn
|
||||
Status: Draft
|
||||
Type: Protocol
|
||||
Created: 2018-01-29
|
||||
Discussion: <url>
|
||||
|
||||
|
||||
## Abstract
|
||||
|
||||
Confidential Transactions (CT) [[1]](#see-also), (as implemented by [Phase I](bsip-0008.md) of Stealth development), solves the linkability and value-hiding problems, but not the traceability problem. CT transfers are traceable on the blockchain, meaning that for any given transaction, a history of prior transactions can be determined. If the set of antecedents is large, then there is a great degree of plausible-deniability regarding the origins of the hidden assets. However, if the set is small, it is possible to determine with increasing probability where the assets originated from. A solution to this is to “mix” transaction inputs with unrelated users so as to increase the traceability set. Some privacy blockchains rely on a mechanical mixing or “tumbling” process to increase the traceability set, however this approach has drawbacks. Monero has a very clever scheme of using ring signatures to automatically and randomly mix in unrelated inputs on every transaction, guaranteeing that even newly blinded funds are mixed with with inputs having a rich history. It is proposed, as a component of [Stealth development Phase II](bsip-1200.md), to implement a similar mechanism for BitShares.
|
||||
|
||||
## Motivation
|
||||
|
||||
Stealth can be thought of as a constellation of privacy-preserving features implemented on (or planned for) the BitShares blockchain. "Privacy" here is a set of specific goals:
|
||||
|
||||
* Untraceability
|
||||
* Unlinkability
|
||||
* Value/Asset hiding
|
||||
* Anonymity
|
||||
|
||||
Although Confidential Transactions (CT) provides good solutions to unlinkability and value hiding, (which together help but do not fully solve anonymity), the transactions currently supported on the network are fully traceable. This means it is possible generate a history all prior transactions leading up to a particular transaction output, including a set of originating transactions wherein public balances were blinded. For outputs which are "close" to their originating transactions, it may be possible possible to identify a small set of non-anonymous originating actors, and to make estimates of the possible maximum value amount of an output (by assuming it can be no larger than the sum of all originating transactions in its history).
|
||||
|
||||
What we seek is a method to make it unknowable *which* prior transaction outputs were consumed in the generation of a new transaction output. Although it seems a tall order (how can a node validate that a sum of inputs balances a set of outputs when it is unknown which inputs are involved?), a solution actually comes in the form of a ring signature protocol developed for the Monero project. <!-- TODO: check specific heritage of this protocol -->
|
||||
|
||||
The ring signature strategy in Monero has gone through two major developmental stages. In the first stage, transaction amounts were not blinded (although pseudo-blinding was achieved by composing value transfers from an aggregate of round-number individual transactions). In the second stage, the ring signature authorization protocol was combined with Confidential Transactions to form the RingCT protocol [[2]](#see-also), in which transfers are both value-blinded and untraceable. Since BitShares already implements CT, the adoption of RingCT into BitShares Stealth operations can be seen as an improvement upon an existing feature.
|
||||
|
||||
## Rationale
|
||||
|
||||
Although BitShares is an account-based blockchain, in which value-transfer operations are a simple transfer of balance from one account to another, Stealth operations on the BitShares blockchain instead follow a **UTXO model**. Stealth transactions produce "**transaction outputs**" (TXOs) which represent individual balance amounts under the control of someone possessing the appropriate secret key. These TXOs are "unspent" (UTXOs) until they are involved in a downstream transaction, at which point they are considered destroyed and no longer spendable. (To partially spend a UTXO, a transaction consuming it would need to produce two outputs: one to the intended recipient, and one back to the sender as "change.")
|
||||
|
||||
A transaction in a UTXO-based blockchain is simply a list of inputs (UTXOs which will be destroyed) and a list of outputs (newly-generated UTXOs). Validating such a transaction involves confirming that the value sum of inputs equals the value sum of outputs plus fees, and that appropriate authorization is provided for all inputs.
|
||||
|
||||
Because the list of inputs is part of the transaction, all UTXOs have a traceable history.
|
||||
|
||||
Ring signatures are a signature scheme in which, for a given set of credentials, a signature is provided proving that at least *one* of the credentials authorized the transaction, but it cannot be determined by a third party *which* credential it was that signed it. Thus ring signatures provide **plausible deniability**. All involved credentialed parties can mutually point fingers at each other, saying, "it wasn't me." <!-- CITE -->
|
||||
|
||||
Ring signatures can provide untraceability in Stealth transactions in the following way: For a given transaction, a set of inputs is collected which is *larger* than the set needed to cover the the intended transaction outputs. The additional inputs should include inputs for which the spender does not have authorizaton to spend. A signature is provided proving that at minimum *enough* inputs are authorized to cover the outputs, however an external observer cannot determine which inputs are thereby consumed. Double-spending of inputs is prevented by the provision of a "**key image**" for each actually-spent input. A key image is a piece of data that uniquly derives from the consumed input, but which cannot be matched to it. A subsequent spend of the same input would produce the same key image, alerting the network to the attempt at a double spend. Now, the set of inputs to any transaction includes not only the actually-consumed inputs, but also a large set of "red herring" inputs, which achieve two important aims for untraceability:
|
||||
|
||||
1. A degree of plausible-deniability for the authorizer of any individual transaction, and
|
||||
2. An enormously larger set of prior transactions that form the "history" of the transaction, implicating a *much* larger set of originating transactions than is actually involved in the true history of the transaction.
|
||||
|
||||
It should be noted that one drowback of this scheme is that it is no longer possible to determine which UTXOs are spent vs. unspent, and this has implications for database pruning. However, the Monero chain has been functioning with this limitation for several years now without hitting a performance bottleneck. Additionally, the Monero team has projected that performance growth will keep pace with database size, even absent pruning of spent TXOs. (CITE). (A review of this projection and discussion of its implication for the BitShares chain is in the Discussion section.)
|
||||
|
||||
## Specifications
|
||||
|
||||
(Detailed description of RingCT with annotations for how it would be adapted to BitShares Stealth transactions.) [[2]](#see-also)
|
||||
|
||||
## Discussion
|
||||
|
||||
### Overview of alternative untraceability solutions
|
||||
|
||||
(Compare/contrast with other schemes for providing untraceability, including ZeroCoin accumulators, master-node facilitated tumbling, MimbleWimble, etc.)
|
||||
|
||||
#### Mimblewimble
|
||||
|
||||
* PRO: Supports a sort of automated, non-interactive aggregate signature scheme (end result similar to CoinJoin), facilitating untraceability at the blockchain level (although not necessarily at the network-snooping level).
|
||||
* CON: Requires communication between sender and recipient.
|
||||
* [[Jed2016]](#see-also), [[PoelMW]](#see-also)
|
||||
|
||||
#### CoinJoin, CoinSwap, etc.
|
||||
|
||||
* In [1], Maxwell states "[CT is] compatible with CoinJoin and CoinSwap, allowing for transaction graph privacy as well while simultaneously fixing the most severe limitation of these approaches to privacy (that transaction amounts compromise their privacy)."
|
||||
* ((This still needs to be researched by this author but I believe these protocols involve mixing with contemporaneous participants, many of whom may be nefarious actors. RingCT allows mixing with historical transactions, and reuse of historical transactions, greatly broadening the set of available mix-in transactions. TODO: confirm this disadvantage.))
|
||||
|
||||
* Dash (http://dash.org) uses a system of "master nodes" to coordinate an opt-in mechanism of "pre-washing" coins via several rounds of mixing with other participants where each round of washing is a CoinJoin-like process. (https://dashpay.atlassian.net/wiki/spaces/DOC/pages/1146924/PrivateSend)
|
||||
|
||||
#### Accumulator Schemes, e.g. ZeroCoin
|
||||
|
||||
* Spending a coin into the accumulator produces receipt that can be used to withdraw a coin from the accumulator later. The withdraw operation cannot be linked to the orignal deposit operation. Untraceability os provided by the fact that the "plausible deniability set" of users who might be responsible for the coin is the set of all users who have deposited coins into the accumulators. This can be a very large set.
|
||||
* Pros:
|
||||
* Large deniability set
|
||||
* Conceptully simple mechanism
|
||||
* Possible to audit supply
|
||||
* Cons:
|
||||
* Depends on a **trusted setup**, which, if compromised, could allow theft or counterfeit of coins
|
||||
* (NOTE: Announcement by ZCoin team of an upgrade that eliminates need for trusted setup) (CITE)
|
||||
* [[Yap2017]](#see-also), [[GrothSigma]](#see-also)
|
||||
* Mechanism to transfer coins between users while the coins are *inside* the accumulator is unclear/unknown (to this author) or impossible. Thus an accumulator may be a good way to wash or hide your own funds, but is not a good solution for creating a balance that one easily use in cash-like user-to-user transactions.
|
||||
|
||||
### Scaling challenges in a Ring-Sig scheme
|
||||
|
||||
(Discussion of the implications of not pruning spent TXOs.)
|
||||
|
||||
## Summary for Shareholders
|
||||
## Copyright
|
||||
|
||||
This document is placed in the public domain.
|
||||
|
||||
## See Also
|
||||
|
||||
[1] Confidential Transactions (Greg Maxwell) - https://people.xiph.org/~greg/confidential_values.txt
|
||||
|
||||
[2] Ring Confidential Transactions (Shen Noether) - https://eprint.iacr.org/2015/1098
|
||||
|
||||
[Jed2016] Mimblewimble (Tom Elvis Jedusor) - https://scalingbitcoin.org/papers/mimblewimble.txt
|
||||
|
||||
[Poel2016MW] Mimblewimble (Andrew Poelstra) - https://download.wpsoftware.net/bitcoin/wizardry/mimblewimble.pdf
|
||||
|
||||
[Yap2017] Zcoin moving beyond trusted setup in Zerocoin (Reuben Yap) - https://zcoin.io/zcoin-moving-beyond-trusted-setup-in-zerocoin/
|
||||
|
||||
[GrothSigma] - One-out-of-Many Proofs: Or How to Leak a Secret and Spend a Coin (Jens Groth and Markulf Kohlweiss) - https://eprint.iacr.org/2014/764.pdf
|
264
bsip-1203.md
Normal file
264
bsip-1203.md
Normal file
|
@ -0,0 +1,264 @@
|
|||
BSIP: 0053
|
||||
Title: Blockchain scanning for inbound Stealth transactions
|
||||
Authors: Christopher J. Sanborn
|
||||
Status: Draft
|
||||
Type: Protocol
|
||||
Created: 2018-01-29
|
||||
Discussion: https://github.com/bitshares/bsips/issues/91
|
||||
|
||||
|
||||
## Abstract
|
||||
|
||||
The existing Stealth implementation ([BSIP-0008](bsip-0008.md)) requires the sender to manually communicate *transaction receipts* to the recipients of each transaction to alert them to the presence of an inbound balance transfer, creating a danger of lost funds due to miscommunicated or lost receipts. This BSIP explores options for automated discovery of inbound transactions while still preserving fundamental privacy features of unlinkability and anonymity.
|
||||
|
||||
## Motivation
|
||||
|
||||
"Stealth addresses" are a method of providing _unlinkability_ to blockchain transactions. Unlinkability is a major component of the Privacy Triad: _unlinkability_, _confidentiality_, and _untraceability_. Using a stealth address, a sending wallet is able to compute a child public key that derives from a public key encoded in the address, but which cannot be correlated, or "linked", to the address public key, unless you are either the sender or the receiver. This child key becomes the authorization key for transaction outputs (TXOs) intended for the receiver. As such, third party observers cannot link TXOs to addresses, nor even link together independent TXOs which are destined to the same address.
|
||||
|
||||
Although this is a great benefit to privacy, it complicates the matter of detecting inbound transactions, since a wallet cannot simply scan for transactions which explicitly identify the destination address.
|
||||
|
||||
Existing [Stealth Phase I](bsip-0008.md) functionality already includes the use of stealth addresses, but does not include a solution for detection of inbound transactions. As a result of which, user adoption of the Stealth feature has been very minimal. We propose below a solution to inbound transaction detection as well as some additional enhancements to the stealth addressing scheme, including a proposed new address format that allows for watch-only wallets.
|
||||
|
||||
## Rationale
|
||||
|
||||
A confidential transaction (cTX) does not identify the recipient. As such, there is no direct way for a wallet to use only its Stealth address to query the p2p network for inbound transactions. In the current "phase one" implementation of Stealth ([BSIP-0008](bsip-0008.md)), inbound discovery is a manual process requiring the sender to communicate "transaction receipts" to the intended recipients of each transaction output in order to alert each recipient of their incoming balance. Transaction receipts are encrypted data structures that embed the Pedersen commitment of the transaction output and the value and blinding factor that the recipient needs to "open" the commitment. Additionally, the receipt records the one-time public key which the recipient must use to derive the private key offset needed to spend the incoming coin, via a shared-secret procedure between the one-time key and the recipient's address key. The need to communicate transaction receipts is burdensome and introduces substantial risk of lost funds due to failure to communicate or retain receipts.
|
||||
|
||||
_Keys involved in a cTX output (cTXO):_
|
||||
* **One-Time Key (OTK)** — The sender generates this key (public and private) from randomness and uses it to generate a shared-secret between the OTK and the recipient's Address ViewKey. The OTK PubKey will be clear-text encoded in the Tx receipt, and optionally also recorded in the transaction output to enable automated discovery.
|
||||
* **Address Keys (ViewKey and SpendKey)** — These are public keys encoded in the recipient's stealth address. The goal of a stealth address scheme is to _not_ identify these public keys in any transaction output. A long-form address encodes _two_ public keys, referred to as ViewKey and SpendKey. The SpendKey serves as a base point from which individual Tx output AuthKeys are computed as an offset, and the ViewKey is used with the OTK to compute that offset. A short-form address encodes only a single public key, which serves as both the ViewKey and SpendKey.
|
||||
* **Tx Output Authorization Key (AuthKey)** — This public key will be recorded in the confidential transaction output (cTXO) as the key which is authorized to spend the commitment. This key is offset from the address SpendKey by a secret offset that only the sender and recipient can calculate (from the shared secret between OTK and ViewKey). The sender can only know the offset, but not the full secret key to the AuthKey. The recipient, knowing the private key behind the SpendKey, can compute the private key to AuthKey and therefore can spend the commitment.
|
||||
|
||||
Automated discovery could be enabled if the receipt were embedded within the transaction data structure and if an aspect of that data structure supported a challenge condition which the recipient could recognize.
|
||||
|
||||
Current network rules allow for a receipt to be embedded in each Tx output via a `stealth_memo` field which is formatted in a similar way as the encrypted memos that may accompany regular (non-Stealth) transfer operations. These memos are composed of a header specifying the OTK PubKey and the "message PubKey" for which the recipient holds the corresponding private key, followed by cipher text which is AES encrypted with a shared-secret key between the OTK and the message PubKey. For this `stealth_memo` field, the current behavior of the CLI reference wallet is to use the recipient's Address PubKey as the message PubKey. Although this is a reasonable choice for encrypting message text generally, it has the severe downside of identifying the recipient's Address PubKey in the memo header, and therefore breaks anonymity and negates the unlinkability provided by using a stealth address scheme. For this reason, the CLI reference wallet currently does _NOT_ actually embed the memo in the Tx ouput but instead Base58 encodes it and prints it to the screen, calling it a "transaction receipt." The sender must manually, and secretly, transmit this to the recipient via a side channel.
|
||||
|
||||
**Stealth Memo structure: (Stealth I)**
|
||||
|
||||
<span></span> | <span></span>
|
||||
-----: | :---
|
||||
**One-time PubKey:** | Chosen from randomness by sender **_(33 bytes)_**
|
||||
**Message PubKey:** | Public key controlled by recipient. **_(33 bytes)_**<br>
|
||||
**Cipher Text:** | AES encrypted message, using _key ← Shared(OTK,MPK)_
|
||||
|
||||
_Current Stealth I behavior is to use the Address PubKey as the message PubKey, which reveals intended recipient!!_
|
||||
|
||||
A very simple solution would be to change the behavior of embedding the Address PubKey in the message PubKey field, and to instead record the Tx output AuthKey in this slot. Because the recipient is also able to derive this AuthKey through knowledge of her own address private keys (in combination with the OTK recorded in the header), the recipient would simply need to test the OTK against each of their own Address Keys to see if the resulting AuthKey matches the one in the header. If it does, then the output is recognized as destined to the recipient, even though the recipient's Address PubKeys are not identified in the memo header. The computational cost of this is one Diffie Hellman round, a hash operation, and a child key derivation. It should be noted that the AES encryption key should still be computed from the shared secret between the OTK and the address ViewKey, however, as this will allow view-only wallets which cannot compute the private key behind the AuthKey to decrypt the memo and tally the incoming transaction.
|
||||
|
||||
**Stealth Memo structure: (Proposed: Stealth II)**
|
||||
|
||||
<span></span> | <span></span>
|
||||
-----: | :---
|
||||
**One-time PubKey:** | Chosen from randomness by sender **_(33 bytes)_**
|
||||
**cTXO AuthKey:** | Child public key of the stealth address and the OTK. **_(33 bytes)_**<br>
|
||||
**Cipher Text:** | AES encrypted message, using _key ← Shared(OTK,ViewKey)_
|
||||
|
||||
_Proposed Stealth II behavior is to embed the AuthKey in the second slot, while still encrypting the message data with a shared key between the OTK and the Address key (specifically, the ViewKey so that watch-only wallets can read the commitment data)._
|
||||
|
||||
To support this strategy, a wallet will need to inspect all cTX activity on the network and test the challenge conditions on each transaction. This could be achieved if API nodes are extended to provide an API call to retrieve `stealth_memo` fields from all cTXOs appearing in a specified block range. The wallet could simply download the memos, test the challenge on each one, and identify and decrypt the ones that are destined to the wallet. No need would remain to manually transmit transaction receipts. The receipts would be embedded, compactly and unlinkably, in the Tx outputs.
|
||||
|
||||
## Specifications
|
||||
|
||||
We specify two protocols. In the first subsection, [_Wallet procedure..._](#wallet-procedure-for-recognizing-own-commitments), we specify the recognition protocol by detailing wallet behaviors for:
|
||||
* Creating transaction outputs that can be recognized by their recipients, and,
|
||||
* Recognizing transaction outputs that are destined to the wallet.
|
||||
|
||||
And in the second subsection, [_API requirements..._](#api-requirements-to-allow-detection-of-inbound-commitments), we propose a new API call for querying nodes for transaction outputs to be scanned for recognizable markers. This is an added feature for API nodes and does not involve any consensus changes.
|
||||
|
||||
### Wallet procedure for recognizing own commitments
|
||||
|
||||
Assumptions:
|
||||
|
||||
1. Wallet has access to a set of private keys corresponding to stealth addresses which may own commitments on the blockchain. These private keys are needed to "recognize" incoming transactions. If the wallet is a watch-only wallet for a particular address, then it is assumed to have the private and public ViewKey, but only the public SpendKey.
|
||||
2. Wallet can query an API node for commitments occurring between specified block heights, to obtain sets of embedded receipts to scan for owned commitments. ([See below](#api-requirements-to-allow-detection-of-inbound-commitments) for this process.)
|
||||
|
||||
We detail procedures for stealth address formats which encode either a single public key, or two distinct public keys in which one key is the ViewKey and the other the SpendKey. The single-key format is already in use on the BitShares network and is borrowed from the original Confidential Transactions specification. The dual-key format allows for additional wallet features and is borrowed from CryptoNote-based coins such as Monero. No changes to the network nodes are required for wallets to support dual-key address formats. In fact, the single-key format can be thought of as a special case of the dual-key format in which the same key is used as the ViewKey and the SpendKey.
|
||||
|
||||
**Address Formats:**
|
||||
|
||||
| Format:
|
||||
:------:|--------
|
||||
**CT-style:** | Single public key and checksum. Public key _A_ serves both viewing and spending roles.<br><br> Format: `BTSaaaaaaaaaaaaaaaaaaaacccc`
|
||||
**CryptoNote-style:** | Two public keys plus a checksum. Public key _A_ serves the viewing role and public key _B_ serves the spending role.<br><br> Format: `BTSaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbcccc`
|
||||
**Invoice Nonce:** | This one encodes a single PubKey serving both the viewing and spending role, but also includes a 64-bit "nonce" or "tag" that the spending wallet is to include in the encrypted memo part of the cTXO, allowing the receiver to interpret payment as being applied to a specific invoice. <br><br> Format: `BTSaaaaaaaaaaaaaaaaaaaannnnnnnncccc`
|
||||
|
||||
_(In the address formats above we consider the part following the "BTS" identifier to be Base58 encodings of the concatenated byte buffer representations of public keys and checksum bytes. C.f. [Base58Check](https://en.bitcoin.it/wiki/Base58Check_encoding) encoding.)_
|
||||
|
||||
|
||||
The dual-key format separates the duties of spending a commitment from those of reading the commitment, such that a person in possession of only the "viewing key" (the private key corresponding to the additional pubkey in the address) can discover, interpret, and tally incoming transactions, but _cannot_ spend them. The "spending key" (private key corresponding to the primary pubkey in the address) is needed to authorize the spending of a commitment. The dual-key address format and signing procedures are described in detail in [[vS13]](#references) and reviewed below.
|
||||
|
||||
#### Procedure for single-key stealth addresses (CT-style)
|
||||
|
||||
Recognizability depends on there being a deterministic relationship between the AuthKey that authorizes expenditure of a particular cTXO, the one-time key (OTK) that the sender generated randomly for the cTXO, and the recipient's Address key (or keys).
|
||||
|
||||
We assume that the stealth address encodes public keys corresponding to two purposes: discovery, and expenditure. When an address encodes only one public key, that key is used for both purposes. We refer to the key for discovery as the "view" key, and denote the private, public pair as _(v, ViewKey)_. For spending, we denote the key pair as _(s, SpendKey)_.
|
||||
|
||||
The AuthKey for a cTXO is an EC point summation of the address's SpendKey and an EC point "offset," which, for present purposes we will denote by the private, public pair _(o, Offset)_, with _Offset = o*G_, where _G_ is the generator point for the curve.
|
||||
|
||||
_AuthKey = SpendKey + Offset_
|
||||
|
||||
Anonymity is preserved so long as only the sender and the receiver are able to compute _o_ and _Offset_. The algorithm for computing _Offset_ is a deterministic function of the OTK and ViewKey only, (and not the SpendKey). This allows the the recipient to recover the SpendKey by simple subtraction of _Offset_ from the AuthKey. The recipient's wallet then compares the computed SpendKey against the address SpendKey. The wallet may even compare against a whole list of SpendKeys that the wallet may have used to generate an address family with a common ViewKey, allowing for differentiable invoices, without sacrificing efficiency of scanning. (See _[address-per-invoice](#utility-of-dual-key-addresses)_ below.)
|
||||
|
||||
Algorithm | Description / Specification
|
||||
:---:|:---------------------------
|
||||
_Shared(a,B) → secret <br> Shared(A,b) → secret_ | This yields a "shared secret" between public keys _A_ and _B_ computable only by parties possessing at least one of the private keys _a_ and _b_.<br><br> _secret = SHA512(P<sub>X</sub>)_; _P = aB = Ab_<br><br>For BitShares Stealth, the secret is a byte buffer (64 bytes) computed from the SHA512 hash of the encoded _X_ coordinate (32 bytes) of EC point _P_. (c.f. [EC Diffie-Hellman](https://en.wikipedia.org/wiki/Elliptic-curve_Diffie–Hellman).)
|
||||
_ChildOffset(B,index) → offset_ | This yields an integer-valued private key _offset_ that generates the keypair _(offset, Offset = offset*G)_. The offset is considered to be a "child" of key _B_, and the parameter _index_ is a byte buffer.<br><br> _child = BigInteger(SHA256(Compressed(B)_ || _index))_<br><br>_Compressed(B)_ refers to the SEC1 "compressed" representation of public key _B_. The || symbol refers to concatenation.
|
||||
|
||||
**Sending:**
|
||||
|
||||
The sender's procedure for computing the offset and generating the AuthKey for the cTXO is detailed as follows:
|
||||
|
||||
<ol>
|
||||
<li> Compute a "shared secret" between between the sender and receiver:
|
||||
|
||||
_secret = Shared(otk, ViewKey)_
|
||||
|
||||
The sender must be careful to leak neither the shared shared secret nor the private _otk_ key.
|
||||
</li>
|
||||
<li> Compute the OffsetKey as a child of the ViewKey, using a SHA256 hash of the shared secret as a child index:
|
||||
|
||||
_childindex = SHA256(secret)_<br>
|
||||
_offset = ChildOffset(ViewKey,childindex)_<br>
|
||||
_OffsetKey = offset*G_
|
||||
</li>
|
||||
<li> Compute the AuthKey by summing SpendKey and OffsetKey:
|
||||
|
||||
_AuthKey = SpendKey + OffsetKey_
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
**Receiving:**
|
||||
|
||||
The receiver, having acquired a list of cTXO metadata that includes _OTK_ and _AuthKey_, goes through the following process to test for ownership:
|
||||
|
||||
<ol>
|
||||
<li> Compute a "shared secret" between between the sender and receiver:
|
||||
|
||||
_secret = Shared(OTK, viewpriv)_
|
||||
</li>
|
||||
<li> Compute the OffsetKey as a child of the ViewKey, using a SHA256 hash of the shared secret as a child index:
|
||||
|
||||
_childindex = SHA256(secret)_<br>
|
||||
_offset = ChildOffset(ViewKey,childindex)_<br>
|
||||
_OffsetKey = offset*G_
|
||||
</li>
|
||||
<li> Recover the public SpendKey by subtracting OffsetKey from AuthKey:
|
||||
|
||||
_SpendKey = AuthKey - OffsetKey_
|
||||
|
||||
</li>
|
||||
<li> Compare the recovered SpendKey against all wallet SpendKeys that may have been used with the ViewKey to generate an address. If one matches, then the cTXO is "recognized." To later spend the cTXO, the wallet computes the private authorization key as:
|
||||
|
||||
_authpriv = spendpriv + offset_
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
Thus, a wallet may undertake to periodically download and scan the metadata for Stealth transactions and test for outputs that can recover a wallet's public SpendKey from knowledge of the private ViewKey.
|
||||
|
||||
##### Embedding recognizability data in the transaction
|
||||
|
||||
For the recipient to have the practical ability to recognize a cTXO as their own, the cTXO, as recorded on the blockchain, must include the following two items: 1.) The one-time PubKey (OTK) that the sender generated for shared-secret generation, and, 2.) the authorization PubKey (AuthKey) of the cTXO. Because the AuthKey is computed deterministically from _Shared(OTK,AddrKey)_, it stands that if the recipient can generate the same AuthKey, then the cTXO belongs to them.
|
||||
|
||||
The structure of a cTXO is as follows:
|
||||
|
||||
_Field_ | _Purpose_
|
||||
-------:|:-------
|
||||
**`commitment`:** | Blinded value commitment _(EC curve point, 33 bytes)_
|
||||
**`range_proof`:** | Proof data supporting transaction validity _(0 to ~5 KiB)_
|
||||
**`owner`:** | BitShares owner structure specifying weighted list of keys or accounts that may spend this commitment. (Typically lists just one public key, the "AuthKey" for the cTXO.)
|
||||
**`stealth_memo`:** | Also known as the "transaction receipt" when transmitted off-chain.<br><br> **`one_time_key`:** _(EC curve point, 33 bytes)_<br> **`to`:** Use the AuthKey here! _(EC curve point, 33 bytes)_<br> **`encrypted_memo`:** Data that recipient needs to "open" the commitment.<br><br> _The stealth memo is optional as far as the network is concerned, but essential if you want the recipient to be able to detect the incoming transaction without sending a "receipt."_
|
||||
|
||||
_(An example transaction showing all these fields can be seen in [block 22157273](https://cryptofresh.com/tx/8182e9d78cbce7df281bc252a9e6d87566ca0622). In this Tx, the stealth_memo '`to`' field unwisely names the recipient's address key, rather than the cTXO Auth key, and thus breaks unlinkability.)_
|
||||
|
||||
Since the `stealth_memo` field can be used to record both the OTK and the AuthKey, all the wallet needs to do to scan for incoming transactions is to download batches of stealth memos and, for each one, test whether the combination of the OTK and the wallet's Address key yields the AuthKey. If it does, then derive the AES decryption key from _Shared(OTK,ViewKey)_ and use that to read the additional data in `encrypted_memo`.
|
||||
|
||||
Structure of `encrypted_memo`:
|
||||
|
||||
_Field_ | _Purpose_
|
||||
-------:|:-------
|
||||
**`from_key`:** | Original use:<br><br><ul>Identifies address key of sender **(optional)**. _(EC curve point, 33 bytes)_</ul>Alternate possible uses:<br><br> <ul><li>Instead of ID'ing the 'from' address, could use this field to embed an _invoice nonce_ to allow receiver to correlate payment to an invoice.</li></ul>
|
||||
**`amount`:** | Value of commitment. _(Integer, 32 bytes)_
|
||||
**`blinding_factor`:** | Blinding factor. _(Integer, 32 bytes)_<br><br>_Note: Except when a blind_sum is needed, the blinding factor is deterministic from a hash of the shared secret, meaning this field can potentially be repurposed or omitted. To guarantee that the blinding factor can always be deterministic, transactions can be padded with a commitment to zero to absorb the blind_sum._
|
||||
**`commitment`:** | The Pedersen commitment. _(EC curve point, 33 bytes)_<br><br> _Note: This field is redundant, since the commitment is determined by_ C = amnt * H + blind * G, _and could potentially be omitted._
|
||||
**`check`:** | Checksum to confirm correct decryption. _(4 bytes)_
|
||||
|
||||
_(TODO: How is this serialized? Do omitted fields "take up space"? Can fields be chosen a la carte? How hard will it be to extend this memo format, for, say, multiple assets in the case of CA? See fc::raw::pack.)_
|
||||
|
||||
|
||||
### API Requirements to Allow Detection of Inbound Commitments
|
||||
|
||||
To monitor for incoming transactions to a particular wallet, a wallet need only download sets of `stealth_memo` structures to test for recognition. The full cTXO (including Pedersen commitment, owner structure, range proof, etc.) need not be downloaded. Because the encrypted data inside the memo indicates the Pedersen commitment, the wallet will know which cTXO it has recognized. (Witness nodes index cTXO's by Pedersen commitment.)
|
||||
|
||||
(Discuss here a proposed API call for retrieving stealth_memos by block height range)
|
||||
|
||||
To know whether a cTXO is still unspent (e.g. by another instance of the wallet), a wallet could attempt to retrieve the corresponding commitment object from an API node. An empty result indicates the commitment has been spent. However, this procedure indicates our interest in a specific set of commitments, and the network traffic generated runs the risk of revealing that those commitments are "linked".
|
||||
|
||||
To prevent this, we propose instead that, in like manner to the downloading of bulk `stealth_memo` structures, that an API call for downloading bulk lists of consumed commitments be implemented, with the download again being over specified block height ranges. A wallet then needs only to test that its own commitments are not on the list of spent commitments.
|
||||
|
||||
In the event that ring signatures are implemented for transaction inputs (see [BSIP-0052](bsip-0052.md)), then instead of downloading a list of consumed commitments, we would instead download a list of used key images, which would serve the same purpose.
|
||||
|
||||
Because a wallet downloads `stealth_memo` structures in bulk over block height ranges, the wallet never reveals to the network its interest in any specific cTXOs. Thus network interaction for monitoring purposes does not undermine privacy.
|
||||
|
||||
NOTE: It is currently possible to retrieve all needed info to support recognition of incoming transactions via Elastic Search queries. This implies: (1) functional wallet behavior can be implemented right away, even if new API calls take longer to implement, and (2) it may be possible to avoid adding new API calls altogether, if the Elastic Search infrastructure is deemed performant enough to support queries from Stealth wallets. (Although intuitively it seems to me an API method would result in a better user experience).
|
||||
|
||||
## Discussion
|
||||
|
||||
### Utility of dual-key addresses
|
||||
|
||||
Utilization of the dual-key address format has numerous interesting use cases, including:
|
||||
|
||||
* The ability to maintain **watch-only wallets**. By entrusting only the View Key to a view-only node, it is possible for this node to monitor for activity to an address without granting spending access to the same node. This allows for such things as: opt-in transparency; cash register monitoring; organizational internal auditing, etc.
|
||||
|
||||
* The ability to use **address-per-invoice** without introducing substantial additional scanning overhead. To use this, one keeps the same viewing PubKey and iterates the Spending PubKey part of the address, generating a distinct address per invoice. When scanning the blockchain, the _Child Offset_ is a function of the shared-secret between OTK and ViewKey, such that _AuthKey = SpendKey + Offset_. To obtain the public SpendKey, a watching wallet can subtract the Offset from the AuthKey to obtain the SpendKey, and simply compare against a list of per-invoice SpendKeys that were used to generate addresses. Adding additional SpendKeys to scan for does not incur any additional EC group operations, merely additional byte-wise comparisons, which are trivial. _(Note that while the invoice addresses generated in this manner are distinct, they are not unlinkably distinct, since they share the viewing component. If a business wants individual invoices to be mutually unlinkable, then this scheme will not be sufficient. However, this is a consideration for a business's off-chain security practices, as the addresses themselves never appear on-chain or in a transaction. An alternate solution which allows even the ViewKey to vary, while still allowing for efficient scanning, is presented in [MRL-0006](https://lab.getmonero.org/pubs/MRL-0006.pdf), however this introduces a change in how the deterministic offsets are generated, which would need to be signaled by a flag in the address format and supported by wallets.)_
|
||||
|
||||
### Possible future extensions
|
||||
|
||||
#### Additional address formats
|
||||
|
||||
The two stealth address formats described above provide for single key and dual key addresses, where the latter allows for separation of transaction monitoring from the ability to spend, allowing for view-only wallets.
|
||||
|
||||
There may be use cases for additional address formats allowing for more complex situations.
|
||||
|
||||
One would be a multi-sig situation in which the address format encodes multiple spending keys and a weighting requirement. Although, this would make the resulting address very lengthy, it would also add an interesting use-case. And, since BitShares authority structures already allow for a vector of authorizing keys and weights, it should be possible to implement the feature on the wallet side, without needing any changes to consensus or API. This idea is not explored further here but merely suggested for future exploration if there is a desire for the feature.
|
||||
|
||||
Another use case for an extended address format would be... (TODO: Discuss including an "invoice nonce" in the address format for correlating incoming transactions to a particular invoice. C.f. Bitcoin where using an address-per-transaction serves both unlinkability as well as invoicing. With Stealth addresses, there is no need to increment addresses for unlinkability, and doing so to facilitate invoicing only increases the scanning overhead by introducing the need to test against additional private keys. But by including an invoice nonce in the address format, which the spending wallet would carry over into the encrypted part of the `stealth_memo`, the recipient can correlate payments to invoices while using only a single address key. This strategy would be similar to the "Integrated addresses" that can be used on the Monero platform. Note, however, that this scheme is largely obsoleted by the simple ability to iterate the SpendKey through a HD address family while keeping the same ViewKey in a dual-key address format.)
|
||||
|
||||
### Pitfalls and Cautions
|
||||
|
||||
#### Specific risks and remedies
|
||||
|
||||
##### Sender leaks private _otk_ or private _shared secret_:
|
||||
|
||||
TODO: analyze
|
||||
|
||||
#### An attack on address key from leak of a transaction private key
|
||||
|
||||
A confidential output will have associated with it an "Output PubKey," or AuthKey. He who can provide a signature from the AuthKey is authorized to spend the commitment. Automated detection of inbound commitments depends on the deterministic computation of an offset between the One-time PubKey (OTK) and the Address SpendKey, which is computed from the shared secret between the sender and receiver. Because only the offset is deterministic, the sender cannot compute the private key to the AuthKey. Only the receiver can do this (by knowing both the offset and the address's private spending key).
|
||||
|
||||
Because AuthKeys are only used once, wallet software designers may be led to believe that the security of the AuthKey private keys are only important up until the commitment is spent. (What would it matter, to leak that private key, when the commitment it authorizes is no longer spendable?) This would be a mistake, however, because anyone who can compute the additive offset can subtract it from the private AuthKey to reveal the address's private spending key. Although the general public is not expected to be privy to that offset, the _sender_ of the output is in possession of the offset (and the ability to compute it due to knowing the random _k_ behind the One-time PubKey). This means the sender would be enabled to compute the address's private key, in the event that the recipient leaks the private AuthKey.
|
||||
|
||||
Thus, wallet designers should be advised to treat the private TXO AuthKeys handled by their wallets with at least as much care as the address private keys, even long after the commitments they authorize have been spent. A leak of a single commitment's PrivKey is tantamount to a leak of the PrivKey for the entire wallet.
|
||||
|
||||
(A similar risk of revealing a parent PrivKey from leak of a child PrivKey and parent XPUB when using non-hardened derivation is noted in the Bitcoin BIP-32 protocol for Hierarchical Deterministic Wallets.)
|
||||
|
||||
## Summary for Shareholders
|
||||
|
||||
Although the goal of this BSIP is to support the long-range vision of [Stealth Phase II](bsip-0050.md), the implementation of this BSIP would provide value _right now_, as it would enable the utilization of even the Phase I _Confidential Transactions_ operations without the reliance on burdensome transaction receipts, which are the primary end-user stumbling block to routine Stealth use.
|
||||
|
||||
We have detailed in this document procedures for producing recipient-recognizable transaction outputs from stealth addresses. Specifically, we have detailed the procedure for _two_ distinct stealth address formats: a single-key address format which is identical to that which is already in use, and a new dual-key address format which separates the duties of monitoring from spending, and thus allows for watch-only Stealth wallets. Support for the dual-key address format would require no network or consensus changes. It requires only wallet support.
|
||||
|
||||
Most of the work needed to implement this BSIP is in the wallet, namely the correct production of recognizable cTXOs and the process of scanning for owned cTXOs. The only network-level change is the addition of two API calls: one to return batches of `stealth_memo` fields included in a block range, and one to return batches of consumed commitments (in the case of CT transactions) or used key-images (in the case of RingCT transactions). These API calls would need to be available on wallet-serving API nodes, but would not be needed on block-producing witness nodes. There are no consensus changes proposed in this document.
|
||||
|
||||
## Copyright
|
||||
|
||||
This document is placed in the public domain.
|
||||
|
||||
## References
|
||||
|
||||
[vS13] - Nicolas van Saberhagen, _Cryptonote v 2.0_, 2013 - https://cryptonote.org/whitepaper.pdf
|
||||
|
||||
[NG17] - Sarang Noether and Brandon Goodell, _An efficient implementation of Monero subaddresses_, 2017 - https://lab.getmonero.org/pubs/MRL-0006.pdf
|
||||
|
||||
## See Also
|
||||
|
||||
* Overview of _Stealth Phase II_ - [BSIP-0052](bsip-0052.md)
|
||||
* [bitshares-stealth-k](https://github.com/Agorise/bitshares-stealth-k) - A Kotlin library for Stealth support in BitShares (in _very_ early development stage)
|
34
bsip-1204.md
Normal file
34
bsip-1204.md
Normal file
|
@ -0,0 +1,34 @@
|
|||
BSIP: 1204 (unassigned)
|
||||
Title: Deterministic addresses for Stealth wallets
|
||||
Authors: Christopher J. Sanborn
|
||||
Status: Draft
|
||||
Type: Informational
|
||||
Created: 2018-01-29
|
||||
Discussion: <url>
|
||||
|
||||
|
||||
## Abstract
|
||||
|
||||
To simplify a wallet owner's backup burden by documenting and standardizing key derivation for Stealth balances from the same backup seeds used to generate the user's regular account keys.
|
||||
|
||||
## Motivation
|
||||
|
||||
Current wallet implementations (e.g. the CLI wallet and Agorise's extensions to the UI wallet) generate a new Brain Key for each Stealth "account" (defined as a confidential balance under the control of a single private key). Since creating a confidential account is a purely client-side activity, (in contrast with a regular account which is registered on the blockchain), there is no automatic association between a confidential balance and a regular account that ostensibly "owns" it, and a backup burden is created for each new confidential balance.
|
||||
|
||||
It would be desireable to give the user the ability to maintain all of her accounts and balances under the control of a single backup key seed or brain key, so that the backup burden can be satisfied just once, at the creation of the user's first regular account. The derivation schemes defined under Bitcoin's BIP-44 provide a natural mechanism for this, and Satoshi Lab's SLIP-48 already define derivation paths for owner, active, and memo keys on BitShares and similar networks.
|
||||
|
||||
We propose here:
|
||||
|
||||
(1) To define additional derivation paths for Stealth accounts, and,
|
||||
|
||||
(2) For backwards compatibility with existing accounts secured by Brain Key, to standardise and document a distinct procedure for deriving Stealth keys from Brain Keys so that the same Brain Key that secures a user's regular account can also be used to secure their confidential balances, if the user desires.
|
||||
|
||||
## Rationale
|
||||
## Specifications
|
||||
## Discussion
|
||||
## Summary for Shareholders
|
||||
## Copyright
|
||||
|
||||
This document is placed in the public domain.
|
||||
|
||||
## See Also
|
30
bsip-1205.md
Normal file
30
bsip-1205.md
Normal file
|
@ -0,0 +1,30 @@
|
|||
BSIP: 1205 (unassigned)
|
||||
Title: Metadata hiding via Garlic Routing and other means
|
||||
Authors: Christopher J. Sanborn
|
||||
Status: Draft
|
||||
Type: Informational
|
||||
Created: 2018-01-29
|
||||
Discussion: <url>
|
||||
|
||||
|
||||
## Abstract
|
||||
|
||||
To provide an overview of strategies that can be used by wallets to prevent leaking of sensitive metadata, e.g. your interest in particular balances on the blockchain, to third parties that may be monitoring network traffic, or to potentially compromised nodes on the BitShares p2p network.
|
||||
|
||||
## Motivation
|
||||
|
||||
Querying a p2p node to check your confidential balances reveals your interest in particular commitments and threatens anonymity by establishing a link between an IP address and a commitment set. New anonymity technologies such as Garlic routing and i2p can be used to ensure that neither network monitoring nor a compromised p2p node can determine the origin of a request regarding a particular set of commitments, thus protecting anonymity.
|
||||
|
||||
Additionally, querying a discrete set of commitments undermines confidential unlinkability. Unlinkability is the inability to determine that multiple independent commitments are controlled by the same party. Although not perfect, a partial solution to this is to use Bloom filters to query a superset of commitments, so that the p2p node will return a mix of linked commitments as well as random commitments, making it difficult for an external observer to establish which commitments are actually of interest to the querying party and which are included by the filter serendipitously.
|
||||
|
||||
There may also exist other strategies of merit to protect unlinkability and privacy generally.
|
||||
|
||||
## Rationale
|
||||
## Specifications
|
||||
## Discussion
|
||||
## Summary for Shareholders
|
||||
## Copyright
|
||||
|
||||
This document is placed in the public domain.
|
||||
|
||||
## See Also
|
Loading…
Reference in a new issue