我开发了一个基于 Beancount 的账本托管服务 HostedBeans,欢迎大家来了解纯文本复式记账并试用我的服务。
标签 #Bitcoin

我对比特币的信心来自哪里

这是我写的第三篇评论比特币的文章,目前比特币的价格在 18000 人民币,前两篇分别是在 2013 年初(600 人民币)和 2013 年末(6000 人民币),在那之后的三年多时间里,我一直保留着大约 1 到 2 个比特币。后来在 2016 年初我准备做一个关于区块链的演讲,于是为了给幻灯片截图,还买入了几十个以太币(Ether),当时以太币可能还没有进入到大众视野。

之前我也说过,我最早了解到比特币是在 2012 年初,那时我对去中心化系统非常感兴趣,当时比特币的价格是 40 元钱,说起来最近「我当初知道比特币的时候才 XX 元钱」已经成了和朋友聊起比特币时的标准开头。从那时起我一直都是比特币的持有者,中间还有一段时间的工作和比特币相关,对技术层面的了解当然是必不可少的,但时间长了也会去想那个终极问题 —— 比特币的价值是来自哪里。

但我们先来解释另外一个问题:为什么最近两个月比特币涨了这么多(从 10000 到 20000)?可能有的人会说因为外汇管制、因为「隔离见证」、因为 WannaCry,但我觉得可以简单地归结为两个字「信心」,价格之所以上涨是因为有更多的人买入,而他们之所以买入是因为他们对比特币有信心,或者说他们对比特币的信心增加了。这种信心的来源是多方面的,可能是你看到了比特币一路上涨、可能是你认识到了比特币是一个可能改变世界的发明,当然更大的可能是看到了身边其他人对比特币的信心,你的信心来自于其他更多对比特币有信心的人,因为有他们的支持,所以你可以放心地买入比特币而不必担心它会一文不值。

如果你认可了比特币的价格来自于信心的话,其实我觉得它就更加符合我们对货币的一般理解了。人民币作为一种法币,即使它只是一张纸钞或者银行中的一串数字,大家对它的信心如此之强,以至于全国十三亿人没有人不收人民币。而且大家甚至认为人民币是唯一可靠的货币,任何其他的货币都会受到这些人的质疑,这种信心来自于几十年里人民币的购买力相对稳定、来自国家政府的背书,当然更多的还是来自于其他人对人民币的信心,你知道你拿着这张纸可以从任何一个中国人那里买到东西。

那么为什么比特币的波动如此之大呢,我觉得一方面是因为它的体量太少,即使按照现在 18000 的价格,总市值大概也只是人民币的千分之一,更小的市值意味着它更容易被操纵。另一方面比特币通过世界各地的交易所可以自由、快速地进行 P2P 的兑换,一旦有影响大家的信心的新闻产生,大家就会第一时间进行买入或卖出操作,更及时地反映到市场价格上;而法币之间的兑换往往要通过银行,再加上一些对于法币兑换的管制,导致信心对价格的影响速度被人为地拖慢了,汇率并不准确地反映当前大家的信心。如果一个法币有着和比特币差不多的市值,并且允许自由兑换,我并不觉得仅仅因为它是法币,它就会比特币的价格更稳定。

比特币的出现和崛起的确让我非常激动,这是一项非常伟大的实验 —— 一种并非政府发行的、去中心化的、基于计算机和互联网的货币能否最终被大家认可。这项实验还远没有结束,包括我在内的无数人用真金白银,以及显卡在继续着这项实验。比特币带动了数百种其他的电子货币,带起了大家对区块链和去中心化技术的兴趣,某种程度上来说可能也带动了显卡和专用芯片的发展,这是比特币在「价格」之外的意义。

1

精子生于 1995 年,英文 ID jysperm.

订阅推送

通过 Telegram Channel 订阅我的博客日志、产品和项目的动态:

王子亭的博客 @ Telegram


通过邮件订阅订阅我的博客日志、产品和项目的动态(历史邮件):

该博客使用基于  Hexo  的  simpleblock  主题。博客内容使用  CC BY-NC-ND  授权发布。最后生成于 2024-04-08.

。Contract 可以通过两种方式去调用其他 Contract 的代码,delegatecall 相当于将另一个 Contract 的代码放到当前上下文执行,就好像引入了一个库函数;而 call 则是发起一笔新的交易去触发另一个 Contract 的逻辑。

那么 Contract 如何从 blockchain 上读取和写入数据呢?这个复杂的工作被抽象为了「状态变量」,上面的 storedData 就是一个状态变量。其实 Contract 执行过程中对状态变量的修改并不会保存到 blockchain 中,因为 Contract 执行的都是确定性的计算 —— Contract 的执行由交易触发,执行过程中只能读取 blockchain 上已有的数据,因此只要我们知道历史上每一笔与这个 Contract 有关的交易,我们就可以随时推算出一个 Contract 在某个时间点上各个状态变量的值。

接下来我来展示一个真正可用的 Contract —— 在 Ethereum 网络的基础上发行一个属于自己的代币:

contract Coin {
    // The keyword "public" makes those variables
    // readable from outside.
    address public minter;
    mapping (address => uint) public balances;

    // Events allow light clients to react on
    // changes efficiently.
    event Sent(address from, address to, uint amount);

    // This is the constructor whose code is
    // run only when the contract is created.
    function Coin() {
        minter = msg.sender;
    }
    function mint(address receiver, uint amount) {
        if (msg.sender != minter) return;
        balances[receiver] += amount;
    }
    function send(address receiver, uint amount) {
        if (balances[msg.sender] < amount) return;
        balances[msg.sender] -= amount;
        balances[receiver] += amount;
        Sent(msg.sender, receiver, amount);
    }
}

代码来自 http://solidity.readthedocs.io/en/latest/introduction-to-smart-contracts.html#subcurrency-example (MIT)

这个名为 Coin 的 Contract 声明了两个状态变量,minter 用来存储这个代币的创建者,在构造函数(function Coin())中将第一笔用于创建 Contract 的交易的发起者赋值给了这个变量;还声明了一个钱包地址到数字的映射表 balances, 用来表示每个持有该代币的地址的余额。

mint 这个函数中先判断了交易的发起者是否是该代币的创建者,如果是的话就按照函数参数,将一定数量的代币加给指定的地址。send 这个函数可以被所有人调用,会从交易发起者的地址扣除一定量的余额(如果有足够的余额的话),加到目标地址上,相当于一个转账的功能。

我们还声明了一个名为 Sent 的事件,事件其实并不会有什么实际的作用,只是便于调试时打印关键性事件,未来也会方便轻量级客户端的实现(轻量级客户端只接受事件而不实际执行 Contract)。

Ethereum 提供了一个叫 Mix 的 IDE 来调试这段代码,在 Mix 的右侧你可以虚构一些 Block 和账户来测试你的 Contract,也可以看到在执行过程中每个状态变量的值的变化情况。值得一提的是 Contract 一旦发布便无法修改,此后的运行完全靠其他人的交易触发,对于每天都在写 Bug 的程序员来讲这一点会令人非常不爽,但是 Contract 的语义本来就是「合约」,一旦你发布了一个合约自然不能去修改它,否则谁还会信任你的合约呢。当然你可以在 Contract 中给自己一些特权(就像前面的 Coin 中那样,只有创建者可以凭空创造代币),但这些代码也存在于 Blockchain 上,其他使用者也是知晓的。

编写完成后我们就可以用 Ethereum 钱包将这个 Contract 发布到网络上了:

发布之后你可以关注这个 Contract,随时点到 Contract 的详情界面:

在左侧可以看到两个状态变量的值,minter 的值就是我自己的地址,balances 因为是一个映射表,所以你可以输入一个地址去查询它的余额。在右侧你可以向这个 Contract 发起新的交易,有一个下拉菜单可以选择 send 或是 mint 函数,你可以填写传递给 Contract 的参数。因为在这里我们发交易的目的是传递一个消息,而非传递 Ether,所以我们不必设置交易的金额。

接下来我要介绍一个很有趣的 Contract,这个 Contract 实现了一个「庞氏骗局」的效果,即你可以向这个 Contract 支付 1 Ether 来加入这个游戏,之后每加入三个人,就会按顺序支付给先加入的人 3 Ether:

contract Pyramid {
    struct Participant {
        address etherAddress;
    }

    Participant[] public participants;

    uint public payoutIdx = 0;

    // events make it easier to interface with the contract
    event NewParticipant(uint indexed idx);

    // fallback function - simple transactions trigger this
    function() {
        enter();
    }

    function enter() {
        if (msg.value < 1 ether) {
            msg.sender.send(msg.value);
            return;
        }

        if (msg.value > 1 ether) {
            msg.sender.send(msg.value - 1 ether);
        }

        uint idx = participants.length;
        participants.length += 1;
        participants[idx].etherAddress = msg.sender;

        NewParticipant(idx);

        // for every three new participants we can
        // pay out to an earlier participant
        if (idx != 0 && idx % 3 == 0) {
            // payout is triple, minus 10 % fee
            uint amount = 3 ether;
            participants[payoutIdx].etherAddress.send(amount);
            payoutIdx += 1;
        }
    }

    function getNumberOfParticipants() constant returns (uint n) {
        return participants.length;
    }
}

代码简化自 https://ethereumpyramid.com/contract.html

代码还算简单,这个 Contract 声明了一个 participants 数组用来按顺序存储所有参与者的钱包地址,还是声明了一个 payoutIdx 用来记录前多少名参与者已经得到了 3 Ether 的返还。enter 实现了这个 Contract 的主要功能,首先是一些参数检查,保证每个参与者都支付了 1 Ether, 然后将新的参与者放到 participants 数组的末尾,最后如果当前参与者的序号刚好是 3 的倍数,就发送 3 Ether 给第 payoutIdx 个参与者,并将 payoutIdx 指向下一个参与者。

参考链接

HashTree:

Bitcoin:

Halting Problem:

Ethereum:

Ethereum Network:

Next of Ethereum:

Contract:

Contract IDE:

利用 Bitcoin 网络进行时间区间证明

有这样一个有趣的话题,如果我在今天,2013 年 12 月 31 日,截取一张截图,那么在事后如何证明这张截图是今天所截取的呢?

同时我希望这个证明足够可靠,关键信息不掌握在少数人手中,任何人无法篡改已经证明的信息,证明不会因为某些机密信息的泄露而失效,且任何人都要可以非常方便地验证这个证明。

乍一看,简单。但细一想,又似乎不可能。

其实这个问题可以分解成两个问题:

「证明这张图必须在某个时间之后才能被截取出来」这个问题简单,只需在截图中包含一些「只有在该时间后才能获取到的信息」,比如当天双色球的中奖号码等等。

这很好理解,如果我在截图中包含了 2013.12.31 的双色球中奖号码,就可以毫无疑问地证明这张图是在 2013.12.31 之后被截取的。

但是,这并不能妨碍我在 2014.1.1 重新截取一张截图,加入 2013.12.31 的双色球号码。所以我们还必须证明「这张图必须在某个时间之前才能被截取出来」。

解决这个问题的关键是要把这张截图的信息,永久地保存到某个可以随时查证的地方,比如我们可以让这张图片登上报纸头条,它就是永远可被查证的了,今后我们可以随时把需要证明的图片与 2013.12.31 的报纸进行对比,证明图片的真伪。

综上只需要在截图中加入当日的双色球号码,并且让它登上报纸头条即可。

——等等,你在开玩笑么。

好吧,所以我要提 Bitcoin, Bitcoin 给我们提供了这样的一个机会,它既是双色球,又是报纸。使用下文的方法进行一次证明只需花费你几分钟的时间,和一点点金钱(几分钱).

首先我们准备一张图片(记作 PIC).

pic.png

因为图片本身很大,对整张图片应用各种加密算法很不划算,所以我们要对这张图片进行散列,如果散列算法足够可靠,我们可以认为散列值就代表了这张图片(记作 HASH), 我们选用在今后很长一段时间都足够可靠的 SHA-256 算法,Bitcoin 网络使用的也是该算法。

HASH = sha256(PIC) = 896c53284a04c3df2c5fe81b1fa228d421ed6c87190da60e153562786346af75

然后我们去瞧一眼 Bitcoin 网络最新的区块(Block) 的散列值,Bitcoin 的区块大约每隔十分钟出现一个,除非你控制了世界上几乎全部的(参与 Bitcoin, 下略)的计算机,否则没有人能预测到它。同时新生成的 Block 会马上被同步到世界上所有的计算机上,事后同样没有人能够篡改。它在此起到了「双色球」的作用。

北京时间 2013.12.31 21:32 产生的最新一个区块的散列值如下,记作 BBH(Bitcoin Block Hash):

BBH = 0000000000000001149d2d7b4fcc693095fef279a1300f938e9cbeec1b43c034

然后我们将最新区块的散列值加到图片上,记作 HASH2:

HASH2 = sha256(HASH1 + BBH) = 277e31d0a5495dbeb642f459be2bcb768d728a7c1e9e008c4d6276dc938d4195

以后我们需要用 HASH2 来表示这张图片(而不是HASH), 因为 HASH2 中包含了最新区块的信息。

至此,我们完成了后向证明。

即,我们证明了「HASH2 只有在拥有 HASH(即 PIC) 且晚于北京时间 2013.12.31 21:32 的情况下才能取得」。

然后,我们使用 HASH2 作为钱包私钥,来生成对应的 Bitcoin 收款地址,因为比特币钱包私钥和收款地址本质上是一对公钥加密算法(如 RSA)的私钥和公钥,因此从公钥无法推出私钥。我们得到了这个收款地址,即证明了我们拥有私钥,再进一步证明了我们拥有 HASH2, HASH, 和 PIC.

在这个过程中,Bitcoin 网络起到了「报纸」的作用,(理想情况下)每笔交易会在下一个区块「截稿」的时候被定格,成为区块的一部分,被同步到世界上所有的计算机上,随时可以查证,又无人可以篡改。

在这一步我使用了 blockchain.info 提供的导入私钥的服务,暂时我还未查证 blockchain.info 以何种格式理解该私钥,但这不影响结论。

我由 HASH2 得出了对应的 Bitcoin 收款地址(记作 PUB):

1ALtyqivh8VgnefQ8okroJUFuNqJYFgSac

然后我向该地址汇入了 0.0001 个 Bitcoin, 以证明我在此时就已经获知了该收款地址,同时支付了 0.0001 个 Bitcoin 的交易手续费(其实可以更少一点), 该交易被收录到了于北京时间 2013.12.31 21:49 产生的新区块中。

至此,我们完成前向证明。

即,我们证明了「我在北京时间 2013.12.31 21:49 之前,就已经拥有该图片了」。

也即,我们在北京时间 2013.12.31 21:49 钱通过向 PUB 中汇款的方式,证明了我们在此刻之前已经获知了 PUB, 而获知 PUB 的前提是 获知 HASH2, HASH, 和 PIC.

至此我我们完成了整个证明过程,证明了我在北京时间 2013.12.31 21:32 - 21:49 这 17 分钟的时间段拥有这张截图,而在这之前或者之后,即使我拥有这种图片,和以上全部信息,也无法做出同样的证明,世上只此一份。

当然,你在今后出示这种图片的同时需要出示 HASH2.

或者你也可以通过某种方式把 HASH2 嵌入到原始图片中(这个工作需要你在做前向证明之前完成).

最后的福利:那个钱包里用于证明的 0.0001 Bitcoin 我没有取走,谁要就拿去吧。

重谈 Bitcoin: 只是一种可能性

我是从 2012 年年初开始关注 Bitcoin 的,当时 Bitcoin 还是 Geek 的代名词,而现在再一提起 Bitcoin, 立刻就会被贴上土豪的标签。

最近一年,Bitcoin 的影响力越来越大,我的圈子里,几乎没有人不知道 Bitcoin 了,连我们的班主任都时不时提上一句两句的。

说实话,大部分人都是在瞎起哄,他们一不懂经济学,二不懂 Bitcoin 的原理,只是知道 Bitcoin 是个价格涨得很快,很多人炒,而且还不大靠谱的东西。

有人说,Bitcoin 没有任何价值,只是一个骗局。相应的,还会有人说,法定货币同样没有价值,价值源自信用。

有人说 Bitcoin 浪费了大量的计算力。相应的,还会有人说,维护法定货币的交易秩序,需要更大的代价。

我觉得,Bitcoin 最大的价值在于,为个人发行货币创造了一种可能性。它不见得是一个好的选择,但从此世界上就多了这么一种可能性。

很多发明都是如此,在当时都只是多了一种可能性罢了。

五年前,如果你想自己发行货币,岂不是天方夜谭?

其实也就是五年多之前,腾讯发行的 Q 币,仅仅是作为一种代金券的存在,就遇到了政策方面不少的阻力,要不是腾讯财大气粗,早就夭折了。

而今天,央行又能对 Bitcoin 说什么呢,前两天央行发过一个《关于防范比特币风险的通知》,看似是在打击 Bitcoin, 但细一品,全是废话,更多的是对 Bitcoin 的无奈。

总之,我觉得这是一种进步。

发明 Bitcoin 并不是一件很困难的事情,它只是将业界早就出现的一些技术组合到了一切,事实上两年前我在构思一个类似的东西,所以我才关注到 Bitcoin 的,Bitcoin 的技术细节无外乎:

要知道这三个难点都是在「无中心」的情况下实现的,这在外行人看来是很难理解的,但如果你对密码学稍微有点研究的话,你会发现至少从技术层面来说,Bitcoin 是无懈可击的。

同时 Bitcoin 也给了其他众多 P2P 网络以启发,虽然 Bitcoin 不是第一个,但它让人们看到了希望:原来有那么多东西都可以以去中心化的方式实现。

随着 Bitcoin 的发展,更多的电子货币纷纷出现,也让我们重新思考了什么是货币,我对经济学毫无研究,但我也有些思考。

我觉得货币本身就不应该具有价值,货币必须是抽象的,这样才能用货币去衡量其他商品的价值,要求货币具有价值是很无理取闹的事情。

如果说货币是基于信用的,那你真的信任法定货币的发行者么?还不是因为货币发行的垄断性,让你不得不信任法定货币,如果有另一种足够可靠的货币呢?

比如政府可以随意地发行货币来稀释你手中货币的价值,银行也可以修改你的存款数字,撤销你的交易,的确这种可能性很小,但凡是人来控制的事情,总有变数。

而 Bitcoin 呢,至少当你发起一笔交易后,没有任何人能够修改或撤销这笔交易,这笔交易永远都是可供考证的,而且不需要第三方就可以核实这笔交易的真实性。

你很难阻止拥有权利的人去作恶,所以最好不要让少数人拥有特权,这是人类最近几千年都在做的事情。

以前我们没有这个可能性,但现在我们有了,随着计算机/互联网的普及,更多的东西会被「数字化」,包括货币。

我觉得货币的数字化是大势所趋,总有一天「数字货币」会代替传统货币,但可能不是 Bitcoin.

推荐另一篇不错的文章:http://www.zhihu.com/question/19653494/answer/17411132

12

精子生于 1995 年,英文 ID jysperm.

订阅推送

通过 Telegram Channel 订阅我的博客日志、产品和项目的动态:

王子亭的博客 @ Telegram


通过邮件订阅订阅我的博客日志、产品和项目的动态(历史邮件):

该博客使用基于  Hexo  的  simpleblock  主题。博客内容使用  CC BY-NC-ND  授权发布。最后生成于 2024-04-08.

辽 ICP 备 13006298 号