【比特币】BIP 0015 详细说明

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析DNS,个人版 1个月
.cn 域名,1个 12个月
简介: BIP 0015 详细说明 BIP: 15 Layer: Applications Title: 别名 Author: Amir Taaki Comments-Summary: No comments yet. Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0015 Status: Deferred Type: Standards Track Created: 2011-12-10BIP 0070(付款协议)可以被视为替代别名。

BIP 0015 详细说明


  BIP: 15
  Layer: Applications
  Title: 别名
  Author: Amir Taaki <genjix@riseup.net>
  Comments-Summary: No comments yet.
  Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0015
  Status: Deferred
  Type: Standards Track
  Created: 2011-12-10

BIP 0070(付款协议)可以被视为替代别名。

使用香草比特币发送资金到目的地,需要一个1Hd44nkJfNAcPJeZyrGC5sKJS1TzgmCTjjZ的地址。 使用地址的问题是他们不容易记住。 如果域名不存在,则需要输入他们喜欢的网站的IP地址。

这个文件的目的是通过仔细的参数来设计一个比特币别名系统。 这是对协议的一个很大的修改,在将来不容易改变,并且有很大的影响。 有第一次纠正的动力。 别名必须是稳健的,安全的。

计划

这里有一些不同的建议和各系统的性能。

FirstBits

FirstBits是将区块链用作地址簿的建议。

当比特币被发送到地址时,该地址就会被记录在区块链中。 因此,知道这个地址存在或确实存在,只要看到有一个付款的地址。 FirstBits是一个具有令人难忘的别名的方法。 首先将地址转换为小写,然后取前几个唯一字符。 这是你的FirstBits别名。

举个例子,布拉格的brmlab hackerspace有一个购买食物或饮料或捐款的地址:

1BRMLAB7nryYgFGrG8x9SYaokb8r2ZwAsX

他们的FirstBits别名变成:

1brmlab

这是足够的信息被给予FirstBits别名1brmlab。 当有人想要购买时,如果没有FirstBits,他们要么手工输入他们的地址,扫描他们的二维码(这需要一个手机,这个作者不拥有),或在互联网上找到他们的地址复制和 粘贴到客户端发送比特币。 FirstBits通过提供简单的付款方式来缓解这种不切实际的情况。

与Vanitygen(虚荣发生器)一起,可以创建令人难忘的唯一命名地址。 地址是有意义的,而不是一个奇怪的字母和数字组合,但添加上下文到目的地。

然而FirstBits有它自己的问题。 一个是可能产生的别名受可用计算能力的限制。 生成一个完整或精确的别名可能是不可行的 - 只有近似值才有可能。 这也是计算资源密集型的,这意味着未来产生独特的别名需要大量的能量消耗,并且在普适计算的环境中不能扩展到家中的个人或手持设备的参与者的水平。

随着网络的增长,FirstBits的规模将非常差。 每个索引器或查找节点需要跟踪每个存在的比特币地址,并提供从别名到这些地址的快速查找。 随着网络线性增长,地址数量应该呈指数增长(假设(n-1)*(n-2)/ 2)的网络效应)使得该方案不可行。

部分merkle根类型的轻客户端依赖于可信第三方的别名查找。 考虑到他们在低资源设备上的典型使用情况,存储每个比特币地址的成本太高。 这个因素多于其他因素,意味着这个方案是次优的,必须被拒绝。

DNS TXT 记录

DNS允许创建包含任意数据的TXT记录。 在比特币别名系统中,由BIP标准共同定义的自定义格式将被用于存储从域名到比特币地址的映射。 这样的格式看起来不在本文的范围之内。

一个问题是,它要求那些希望创建这种映射的人熟悉配置DNS记录,并且能够运行必要的工具集来插入正确的数据。 虽然不是一个大问题,但这是一个可用性问题。

安全方面,DNS是不安全和不安全的设计。 可以通过与另一个主机位于同一网络来欺骗记录。 自二十世纪九十年代以来,DNSSEC幌子下的一系列修改工作已经开始,目前仍在进行中。

截至2011年12月,DNSSEC在互联网上还没有达到事实标准。 如果比特币网络的参与者希望使用DNS TXT记录,则他们除了必须配置DNS之外,还能够设置DNSSEC。 这可能是不可行的,尤其是在一些注册商只通过网页界面访问DNS的情况下。

DNS TXT记录的缺点是更新记录需要时间。 这鼓励人们不要使用每个具有一定安全问题的交易的新地址。

服务器服务

除了使用DNS TXT记录,另一种可能性是使用域名系统查找主机,然后联系预定义的端口上运行的服务,以获得比特币地址。

  1. 用户希望发送到foo@bar.net
  2. 客户端使用DNS查找bar.net的IP地址:123.123.123.123
  3. 客户端连接到端口123.123.123.123:4567,并请求用户foo的比特币地址
  4. 服务器响应地址或错误代码并终止连接。
  5. 客户将资金发送到地址

该服务将负责提供更改和存储服务映射的机制。 可以为希望使用该服务并在服务器上定制其帐户的用户提供前端Web界面。

这种方法具有积极的作用,为实现者提供最好的灵活性,然后将它们存储在数据库或纯文本文件中,然后使用通常用C编写的小型服务器端守护进程快速提供这些记录。这种方法具有高度可扩展性。

但是,这种方法也面临着依赖于DNS的问题,因此也容易受到欺骗。 因此DNSSEC也是必需的。 这种方法比DNS TXT记录稍好,因为它使得插入新用户和修改别名非常容易,这使得人们可以更便宜地运行这些服务器服务。

HTTPS Web服务

HTTPS通过加密连接提供额外的安全层,为用户提供非常需要的隐私。 与使用证书颁发机构一起,它解决了使用DNSSEC的问题,因为会引发错误,有人试图欺骗本地网络上的域名。

当试图发送到:

genjix@foo.org

这个请求在@的最后一个出现处被分解成句柄(genjix)和域(foo.org)。 客户端然后构造一个将查询地址的请求。

https://foo.org/bitcoin-alias/?handle=genjix

比特币别名已经被选为查询后缀,因为它允许这个系统在另一个web根目录中很容易共存,而不用担心名称冲突。

查询将返回一个用于付款的地址。

1Hd44nkJfNAcPJeZyrGC5sKJS1TzgmCTjjZ

每个查询是否返回一个唯一的地址,是否从一个预先存在的地址池中获取一个地址,等等的细节是每个服务器唯一的实现细节。 设置映射映射的别名依赖于可能具有Web界面的站点,并向用户提供免费服务,或者是为预先存在的地址提供私人定制服务。 这是留给管理层的政策,故意不在这里定义。

一个Web服务是微不足道的安装和成本低。 网络上有许多免费的提供商,允许任何具有最基本的网络技术知识的人创建自己的网站。 通过为用户提供一个软件包,任何人都可以快速设置自己的比特币别名。 它可以像PHP脚本一样简单,用户可以使用自定义设置进行编辑并上传自己的网站。

它也可以合理扩展 - 任何希望运行命名服务的人都可以使用各种数据库技术来附加后端,然后为用户提供一个Web前端来自定义和创建自己的别名。

作为一个例子,下面提供了一个天真的实现。

// resolv.h
#ifndef NOMRESOLV_H__
#define NOMRESOLV_H__

#include <string>
#include "curl/curl.h"

using std::string;

/*

这个类解决了服务器查找地址。
为了不与比特币地址冲突,我们在这里指的是人的手柄。
一个句柄的形式是:

   genjix@foo.org

大多数字符对用户名+密码有效(并进行相应处理),但域遵循通常的Web标准。 如果需要,可以粘贴一条路径,

   genjix@bar.com/path/to/

*/

class NameResolutionService
{
public:
    NameResolutionService();
    ~NameResolutionService();

    // Three main methods map to RPC actions.
    string FetchAddress(const string& strHandle, string& strAddy);

private:
    // A POST block
    class PostVariables
    {
    public:
        PostVariables();
        ~PostVariables();
        // Add a new key, value pair
        bool Add(const string& strKey, const string& strVal);
        curl_httppost* operator()() const;
    private:
        // CURL stores POST blocks as linked lists.
        curl_httppost *pBegin, *pEnd;
    };

    // Explodes user@domain => user, domain
    static void ExplodeHandle(const string& strHandle, string& strNickname, string& strDomain);
    // Perform the HTTP request. Returns true on success.
    bool Perform();

    // CURL error message
    char pErrorBuffer[CURL_ERROR_SIZE];
    // CURL response
    string strBuffer;
    // CURL handle
    CURL *curl;
};

#endif
// resolv.cpp
#include "resolv.h"

#include <boost/lexical_cast.hpp>

#include "access.h"

// callback used to write response from the server
static int writer(char *pData, size_t nSize, size_t nNmemb, std::string *pBuffer)
{
  int nResult = 0;
  if (pBuffer != NULL)
  {
    pBuffer->append(pData, nSize * nNmemb);
    // How much did we write?
    nResult = nSize * nNmemb;
  }
  return nResult;
}

NameResolutionService::NameResolutionService()
{
    // Initialise CURL with our various options.
    curl = curl_easy_init();
    // This goes first in case of any problems below. We get an error message.
    curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, pErrorBuffer);
    // fail when server sends >= 404
    curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
    curl_easy_setopt(curl, CURLOPT_HEADER, 0);
    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
    curl_easy_setopt(curl, CURLOPT_POSTREDIR, CURL_REDIR_POST_302);
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
    curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
    curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1);
    // server response goes in strBuffer
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &strBuffer);
    pErrorBuffer[0] = '\0';
}
NameResolutionService::~NameResolutionService()
{
    curl_easy_cleanup(curl);
}

void NameResolutionService::ExplodeHandle(const string& strHandle, string& strNickname, string& strDomain)
{
    // split address at @ furthrest to the right
    size_t nPosAtsym = strHandle.rfind('@');
    strNickname = strHandle.substr(0, nPosAtsym);
    strDomain = strHandle.substr(nPosAtsym + 1, strHandle.size());
}
bool NameResolutionService::Perform()
{
    // Called after everything has been setup. This actually does the request.
    CURLcode result = curl_easy_perform(curl);
    return (result == CURLE_OK);
}

string NameResolutionService::FetchAddress(const string& strHandle, string& strAddy)
{
    // GET is defined for 'getting' data, so we use GET for the low risk fetching of people's addresses
    if (!curl)
        // For some reason CURL didn't start...
        return pErrorBuffer;
    // Expand the handle
    string strNickname, strDomain;
    ExplodeHandle(strHandle, strNickname, strDomain);
    // url encode the nickname for get request
    const char* pszEncodedNick = curl_easy_escape(curl, strNickname.c_str(), strNickname.size());
    if (!pszEncodedNick)
        return "Unable to encode nickname.";
    // construct url for GET request
    string strRequestUrl = strDomain + "/bitcoin-alias/?handle=" + pszEncodedNick;
    // Pass URL to CURL
    curl_easy_setopt(curl, CURLOPT_URL, strRequestUrl.c_str());
    if (!Perform())
        return pErrorBuffer;
    // Server should respond with a JSON that has the address in.
    strAddy = strBuffer;
    return "";  // no error
}

NameResolutionService::PostVariables::PostVariables()
{
    // pBegin/pEnd *must* be null before calling curl_formadd
    pBegin = NULL;
    pEnd = NULL;
}
NameResolutionService::PostVariables::~PostVariables()
{
    curl_formfree(pBegin);
}
bool NameResolutionService::PostVariables::Add(const string& strKey, const string& strVal)
{
    // Copy strings to this block. Return true on success.
    return curl_formadd(&pBegin, &pEnd, CURLFORM_COPYNAME, strKey.c_str(), CURLFORM_COPYCONTENTS, strVal.c_str(), CURLFORM_END) == CURL_FORMADD_OK;
}

curl_httppost* NameResolutionService::PostVariables::operator()() const
{
    return pBegin;
}
</source>

<source lang="cpp">
// rpc.cpp
...

const Object CheckMaybeThrow(const string& strJsonIn)
{
    // Parse input JSON
    Value valRequest;
    if (!read_string(strJsonIn, valRequest) || valRequest.type() != obj_type)
        throw JSONRPCError(-32700, "Parse error");
    const Object& request = valRequest.get_obj();
    // Now check for a key called "error"
    const Value& error  = find_value(request, "error");
    // It's an error JSON! so propagate the error.
    if (error.type() != null_type)
        throw JSONRPCError(-4, error.get_str());
    // Return JSON object
    return request;
}

const string CollectAddress(const string& strIn)
{
    // If the handle does not have an @ in it, then it's a normal base58 bitcoin address
    if (strIn.find('@') == (size_t)-1)
        return strIn;

    // Open the lookup service
    NameResolutionService ns;
    // We established that the input string is not a BTC address, so we use it as a handle now.
    string strHandle = strIn, strAddy;
    string strError = ns.FetchAddress(strHandle, strAddy);
    if (!strError.empty())
        throw JSONRPCError(-4, strError);

    const Object& request(CheckMaybeThrow(strAddy));
    // Get the BTC address from the JSON
    const Value& address = find_value(request, "address");
    if (address.type() != str_type)
        throw JSONRPCError(-32600, "Server responded with malformed reply.");
    return address.get_str();
}

// Named this way to prevent possible conflicts.
Value rpc_send(const Array& params, bool fHelp)
{
    if (fHelp || params.size() != 2)
        throw runtime_error(
            "send <name@domain or address> <amount>\n"
            "<amount> is a real and is rounded to the nearest 0.01");

    // Intelligent function which looks up address given handle, or returns address
    string strAddy = CollectAddress(params[0].get_str());
    int64 nAmount = AmountFromValue(params[1]);
    // Do the send
    CWalletTx wtx;
    string strError = SendMoneyToBitcoinAddress(strAddy, nAmount, wtx);
    if (!strError.empty())
        throw JSONRPCError(-4, strError);
    return wtx.GetHash().GetHex();
}

...

IP交易

一个IP交易是比特币中一个旧的交易格式,被禁用,可能会被弃用。 它涉及被给予一个IP地址付款。 当连接到节点并使用“checkorder”请求他们的公钥时,他们将用以下格式的脚本进行响应:

<public key> OP_CHECKSIG

类似于coinbase输出交易。 IP事务具有能够包含额外的元数据的优点,这在许多事务中可能是有用的。 目前没有进行认证,使得该方案对中间人(MITM)攻击不安全。

此提案旨在为IP事务启用DNS查找。

“checkorder”消息将包含一个目标帐户,该目标帐户可映射到在同一主机下运行的不同的独立密钥对/钱包集。 从checkorder参考信息到本地系统的确切映射是实现定义的。

通过使用DNS查找,通过将公钥存储在DNS TXT记录中,可以缓解IP事务的MITM问题。 这个公钥将被用于所有将来从该主机发出的“回复”消息。 首次使用需要确认接受该公钥; 像SSH一样。 如果“回复”消息与接受的公钥不匹配,则主机将被给出错误。

Namecoin ID

此建议使用Namecoin区块链将别名与比特币地址相关联。 比特币查询名称币结点。 这将检索包含与该别名相关联的比特币地址的结构化数据。

使用像Namecoin这样的分散的域名系统,意味着不像这里列出的其他提案那样需要信任外部服务器或实体。 这表明系统具有高可用性和易于输入的优点(不限制用户创建别名)。

下面介绍两个例子。 第一个显示了一个更简单的格式,而第二个显示了几个比特币地址的结构化格式。

$ namecoind name_show id/khal
 {
   "bitcoin" : "1KHAL8bUjnkMRMg9yd2dNrYnJgZGH8Nj6T"
 }
 ```

$ namecoind name_show id/khal
{
“bitcoin” :
{
“default” : “1KHAL8bUjnkMRMg9yd2dNrYnJgZGH8Nj6T”,
“donation”: “1J3EKMfboca3SESWGrQKESsG1MA9yK6vN4”
}
}



更多可能性:

- 允许安全使用不安全的渠道

你可以把一个网址和一个比特币地址,用来签署的结果。 这意味着对这个URL的查询将返回一个比特币地址和签名。 比特币然后可以检查(使用verify_message函数)返回的地址还没有被另一个替换。

$ namecoind name_show id/khal
{
“bitcoin” :
{
“url” : “http://merchant.com/bitcoin/getnewaddres/“,
“signedWith” : “1KHAL8bUjnkMRMg9yd2dNrYnJgZGH8Nj6T”
}
}


- 允许每次或每个用户获得不同的地址,每个订单等

$ namecoind name_show id/khal
{
“bitcoin” :
{
“url” : “http://merchant.com/bitcoin/getaddres/{Your customer id}”,
“signedWith” : “1KHAL8bUjnkMRMg9yd2dNrYnJgZGH8Nj6T”,
“useOnce”: false
}
}
“`

在上面的例子中,比特币会要求用户输入“Your customer id”,然后在发出http请求之前将该值替换为url。 商家将收到请求,并为用户提供与该客户相关的付款地址。

任何文字可以被放入括号,允许商家以使其适应他们的需求。

  • 规范是可扩展的

可以稍后添加新功能来支持未发现的案例。
有关更多信息,请参阅Namecoin ID的规范。

总结

11年提出来的,现在被搁置,问题是比特币的地址太长,所以想通过别名的方式来解决。

原文档的连接已经失效了,但是内容还能谷歌出来。

参考资料

目录
相关文章
|
1月前
|
存储 安全 区块链
WBTC与BTC的主要区别
WBTC与BTC的主要区别
42 6
|
11月前
|
存储 JavaScript 前端开发
区块链代币支付钱包(trx/trc20代币/usdt)对接开发
区块链代币支付钱包(trx/trc20代币/usdt)对接开发
|
SQL 存储 NoSQL
DAPP币安链BSC/波场链TRC/以太链ETH智能合约代币流动性质押挖矿分红系统开发详细及逻辑
 用户合约在创建时,系统会自动创建一个新的数据库给该合约,所以不同的用户合约的状态数据以数据库进行区隔。在创建合约对应的数据库后,系统会执行合约init_contract函数中的SQL语句,包含非数据库事务的DDL语句,出于安全考虑,一个创建合约的交易或升级合约的交易将会被单独打包到区块中,不能与其他普通合约调用的交易一起打包。
|
存储 安全 算法
以太链ETH丨波场链TRC丨币安链BSC智能合约流动性质押挖矿分红系统开发技术详细及代码部署
以太坊(Ethereum)是一个分布式计算机,有许多的节点,其中的每一个节点都会执行智能合约,然后把结果存在区块链上。由于整个网络是分布式的,且应用就是一个个的状态组成,存储了状态就有了服务;所以它没有一个中心化的结点,任何第三方不能干预,能永不停机。
|
存储 网络协议 区块链
什么是以太链ETH系统开发?ETH以太链dapp智能合约流动性质押挖矿分红系统开发详细及说明
 以太坊是一种区块链的实现。在以太坊网络中,众多的节点彼此连接,构成了以太坊网络:以太坊节点软件提供两个核心功能:数据存储、合约代码执行。在每个以太坊全节点中,都保存有完整的区块链数据。以太坊不仅将交易数据保存在链上,编译后的合约代码同样也保存在链上。以太坊全节点中,同时还提供了一个虚拟机来执行合约代码。
|
安全 程序员 区块链
BlockChain:【中本聪】历史之作《Bitcoin: A Peer-to-Peer Electronic Cash System》 《比特币:一种点对点的电子现金系统》—九页中英文对照翻译
1、了解区块链底层原理技术,还是要看原汁原味的白皮书,对的,就是《Bitcoin: A Peer-to-Peer Electronic Cash System》 2、有些术语翻译或许不太准确,欢迎前来提错误!! 2017-12-30最近一次修改
BlockChain:【中本聪】历史之作《Bitcoin: A Peer-to-Peer Electronic Cash System》 《比特币:一种点对点的电子现金系统》—九页中英文对照翻译
|
存储 区块链 Windows
以太坊钱包Ethereum Wallet C盘数据转移
以太坊钱包Ethereum Wallet C盘数据转移
132 0
|
Shell Linux 区块链
BTC 主网钱包linux安装( 比特币)
比特币是一种实验性数字货币,可以即时支付给世界任何地方的任何人。比特币使用对等技术在没有中央授权的情况下进行操作:管理交易和发行资金是由网络集体进行的。比特币核心(Bitcoin Core)是可以使用这种货币的开源软件的名称。
1127 0
Bytom BIP-32协议和BIP-44协议
我们知道HD(分层确定性)钱包,基于 BIP-32;多币种和多帐户钱包,基于 BIP-44;最近比原社区的钱包开发者对比原的BIP-32和BIP-44协议有疑问,所以我今天就专门整理了一下该协议的内容以及在比原中涉及的代码。
2146 0