diff options
Diffstat (limited to 'bip-0020.mediawiki')
-rw-r--r-- | bip-0020.mediawiki | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/bip-0020.mediawiki b/bip-0020.mediawiki new file mode 100644 index 0000000..a96d8d0 --- /dev/null +++ b/bip-0020.mediawiki @@ -0,0 +1,211 @@ +<pre> + BIP: 20 + Title: URI Scheme + Author: Luke Dashjr <luke+bip@dashjr.org> + Status: Rejected + Type: Standards Track + Created: 10-01-2011 +</pre> + +BIP 0020 is based off an earlier document by Nils Schneider. + +==Abstract== +This BIP proposes a URI scheme for making Bitcoin payments. + +==Motivation== +The purpose of this URI scheme is to enable users to easily make payments by simply clicking links on webpages or scanning QR Codes. + +==Specification== + +=== General rules for handling (important!) === + +Bitcoin clients MUST NOT act on URIs without getting the user's authorization. +They SHOULD require the user to manually approve each payment individually, though in some cases they MAY allow the user to automatically make this decision. + +=== Operating system integration === +Graphical bitcoin clients SHOULD register themselves as the handler for the "bitcoin:" URI scheme by default, if no other handler is already registered. If there is already a registered handler, they MAY prompt the user to change it once when they first run the client. + +=== BNF grammar === + +(See also [[#Simpler syntax|a simpler representation of syntax]]) + + bitcoinurn = "bitcoin:" bitcoinaddress [ ";version=" bitcoinversion ] [ "?" bitcoinparams ] + bitcoinaddress = base58 *base58 + bitcoinversion = "1.0" + bitcoinparams = *bitcoinparam + bitcoinparam = amountparam | labelparam | messageparam | sendparam | otherparam + amountparam = "amount=" amount + amount = amountdecimal | amounthex + amountdecimal = *digit [ "." *digit ] [ "X" *digit ] + amounthex = "x" *hexdigit [ "." *hexdigit ] [ "X" *hexdigit ] + labelparam = "label=" *pchar + messageparam = "message=" *pchar + sendparam = "send=" *pchar + otherparam = pchar *pchar "=" *pchar + +=== Query Keys === + +*label: Label for that address (e.g. name of receiver) +*address: bitcoin address +*message: message that shown to the user after scanning the QR code +*size: amount of base bitcoin units ([[#Transfer amount/size|see below]]) +*send: used to send bitcoin, rather than to request them +*(others): optional, for future extensions + +==== Transfer amount/size ==== + +If an amount is provided, it may be specified either in decimal or, when prefixed with a single "x" character, hexadecimal. +The number SHOULD be followed by "X" <digits> to signify an exponent to the base multiplier. +Thus, "X8" multiplies your number by 100,000,000. +For decimal values, this means the standard BTC unit. +For hexadecimal values, this means ᵇTBC units (which are equivalent to 42.94967296 BTC). +If exponent is omitted, implementations SHOULD assume X8 for decimal numbers, and X4 for hexadecimal numbers. +I.e. amount=50.00 is treated as 50 BTC, and amount=x40 is treated as 40 TBC. +When specifying bitcoin base units, "X0" SHOULD be used. + +Bitcoin clients MAY display the amount in any format that is not intended to deceive the user. +They SHOULD choose a format that is foremost least confusing, and only after that most reasonable given the amount requested. +For example, so long as the majority of users work in BTC units, values should always be displayed in BTC by default, even if mBTC or TBC would otherwise be a more logical interpretation of the amount. + +== Rationale == + +===Payment identifiers, not person identifiers=== +Current best practices are that a unique address should be used for every transaction. +Therefore, a URI scheme should not represent an exchange of personal information, but a one-time payment. + +===Accessibility (URI scheme name)=== +Should someone from the outside happen to see such a URI, the URI scheme name already gives a description. +A quick search should then do the rest to help them find the resources needed to make their payment. +Other proposed names sound much more cryptic; the chance that someone googles that out of curiosity are much slimmer. +Also, very likely, what he will find are mostly technical specifications - not the best introduction to bitcoin. + +==Forward compatibility== +We want URIs generated in 2011 to still work in 2036: think about extensibility. +Of course we can make only educated guesses about the future, but don't act as if there is none. +This should be the best we can do, but it should not be seen as set in stone. +Make it possible for later generations to improve our work, to mend our errors, without breaking the URIs created now. + +== Appendix == + +=== Simpler syntax === + +This section is non-normative and does not cover all possible syntax. +Please see the [[#BNF grammar|BNF grammar]] above for the normative syntax. + +[foo] means optional, <bar> are placeholders + + bitcoin:<address>[;version=1.0][?amount=<amount>][?label=<label>][?message=<message>][?send=<private key>] + +=== Examples === + +Just the address: + bitcoin:1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L + +Address with name: + bitcoin:1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L?label=Luke-Jr + +Request 20.30 BTC to "Luke-Jr": + bitcoin:1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L?amount=20.3X8&label=Luke-Jr + +Request 400 TBC: + bitcoin:1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L?amount=x400X4 + +Request 4000 TBC: + bitcoin:1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L?amount=x4X7 + +Request 5 uBTC: + bitcoin:1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L?amount=5X2 + +Request 50 BTC with message: + bitcoin:1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L?amount=50X8&label=Luke-Jr&message=Donation%20for%20project%20xyz + +Send 1 BTC: + bitcoin:1NS17iag9jJgTHD1VXjvLCEnZuQ3rJED9L?amount=1X8&send=S4b3N3oGqDqR5jNuxEvDwf + +Characters must be URI encoded properly. + +===Sending money via private key=== +To send a payment to someone else first construct a new keypair. You may want to use a [[mini private key format]], or you may also use a full private key for more security depending on the amount being sent and how long you expect to pass before a claim. Now create and publish a transaction with an output of the amount you wish to send. Use this script in that output: + + <pubkey> OP_CHECKSIG + +Construct an address from the public key. Encode the URI as below: + + bitcoin:<address>?send=<base 58 encoded private key> + +You may optionally include amount or message fields as well. In a wallet to claim money sent this way search for an incoming transaction with the output script form above, where <address> matches the public key in the script. When you find the transaction create a claim transaction with an input script of this form: + + <sig> + +This claims the money you were sent. Until your claim transaction has confirmed the sender may take their money back. + +== Reference Implementations == +=== Bitcoin clients === +* [[Spesmilo]] supports all valid Bitcoin URIs, with Windows and KDE integration + +=== Parsing amount === +==== ECMAScript ==== + reAmount = /^(([\d.]+)(X(\d+))?|x([\da-f]*)(\.([\da-f]*))?(X([\da-f]+))?)$/i; + function parseAmount(txt) { + var m = txt.match(reAmount); + return m[5] ? ( + ( + parseInt(m[5], 16) + + (m[7] ? (parseInt(m[7], 16) * Math.pow(16, -(m[7].length))) : 0) + ) * ( + m[9] ? Math.pow(16, parseInt(m[9], 16)) : 0x10000 + ) + ) : ( + m[2] + * + (m[4] ? Math.pow(10, m[4]) : 1e8) + ); + } + +==== Python ==== + m = re.match(r'^(([\d.]+)(X(\d+))?|x([\da-f]*)(\.([\da-f]*))?(X([\da-f]+))?)$', amount, re.IGNORECASE) + if m.group(5): + amount = float(int(m.group(5), 16)) + if m.group(7): + amount += float(int(m.group(7), 16)) * pow(16, -(len(m.group(7)))) + if m.group(9): + amount *= pow(16, int(m.group(9), 16)) + else: + amount *= 0x10000 + else: + amount = Decimal(m.group(2)) + if m.group(4): + amount *= 10 ** int(m.group(4)) + else: + amount *= 100000000 + +==== C# ==== + Regex amountExpression = new Regex(@"^(([\d.]+)(X(\d+))?|x([\da-f]*)(\.([\da-f]*))?(X([\da-f]+))?)$", RegexOptions.IgnoreCase); + Match match = amountExpression.Match(value); + if (match.Success) + { + if (match.Groups[5].Success) + { + long hexDecimal = 0; + if (match.Groups[7].Success) + hexDecimal = Convert.ToInt64(match.Groups[7].Value, 16) * (long)Math.Pow(16, -match.Groups[7].Length); + + long hexExponent = 0x10000; + if (match.Groups[9].Success) + hexExponent = (long)Math.Pow(16, Convert.ToInt32(match.Groups[9].Value, 16)); + + Amount = (Convert.ToInt64(match.Groups[5].Value, 16) + hexDecimal) * hexExponent; + } + else + { + long decimalExponent = 100000000; + if (match.Groups[4].Success) + decimalExponent = (long)Math.Pow(10, int.Parse(match.Groups[4].Value)); + Amount = (long)(decimal.Parse(match.Groups[2].Value) * decimalExponent); + } + } + +[[Category:Developer]] +[[Category:Technical]] +[[Category:BIP|D]] + |