比特币是不是货币?
比特币是不是货币今天晚上和人聊天的时候,提到的了这个话题。我开始从事比特币相关开发也有一段时间了,经常有人会提到这个话题。这个话题比”比特币是什么?”更加具体,我也被问到过多次。本着不重复劳动的初心,特意写这篇小文章来说说我的理解。 回答是否定的,比特币并非货币。 严格的来讲,比特币是一种数字通证。或者从技术角度来讲我们把这类东西都统称为Token。 按照货币学基本原理,货币是可以超发的。因为货币的一个重要基本功能是价值的尺度。我们讲一部手机价值3000元。这里的三千元就等于价值的尺度。它是用来衡量社会财富的标尺。 何为超发呢,超发就是简单来讲可以得到更多。比如政府可以根据经济情况印更多的货币。换句话来说,货币是可以变多的。但是比特币是不可以变多的,它的总量是固定的。 延伸的话题就是,为什么货币必须要超发?因为我们社会财富的增长是必然的趋势。随着生产力会进步,那么必然会有产出更多财富。我们就需要更多的货币来衡量价值。假入我们一共只有一千人民币,我们生产了一部手机,手机定价为一千元。那我们就用一千来衡量手机的价值。但是如果我们生产出两部手机,但是我们还是只有一千元,会怎么样呢...
使用状态码加消息传递库状态
这篇文章是上一篇使用rust写安卓库的续篇,本身按照上一篇文章的介绍已经完全基本讲清楚了使用rust给安卓写库的基本方面,这篇文章继续在之前的状态上补充,力求文章完备。 本文要解决的场景如下 当我们外部调用rust库时难免出现库本身状态出现问题,比如内部错误,比如参数错误。假如我们在只使用同一种语言,这种问题很好处理,善用语言错误处理机制即可。然而我们跨语言就出现了问题,如在之前文章设定的场景:java端的错误是Exception,rust端的错误是Result和Option。 所以我们采用状态码来传递错误信息。着重于传递错误信息。我们把想传递的消息给调用端即可。毕竟作为库的使用者,并不知道库内部的具体信息,只需要知道我作为传递信息者有什么问题就好了。库的问题由库来解决。 在设定以上场景之后,我们的问题就很容易解决。除去错误处理这个杂质,进一步简化问题为如下 调用端传递信息进库,库返回状态(对象)给的调用者。 唯一的问题就是跨语言。(这个属于具体使用rust-jni库的细节,如果要写一个跨语言的库,大体是这种处理方案) 然后我们来写代码(设定场景,java调用rust...
使用rust写安卓库
使用rust写安卓库rust写安卓库也是rust的一个重要应用方向,之前用来写安卓的库的语言大多数都是c/c++。本文不讨论两种(或者叫两类)语言的优劣,只说明如何搭建一个rust-android相互交互的环境。 Android使用Java语言,java与c/c++交互使用jni技术。Android与rust交互也使用jni。在这里我们使用jni-rs库。在使用rust写安卓库之前我们先简化一下问题。先用jni-rs编写一个可以被java调用的库。这个过程可以参考jni-rs的代码说明。但我自己使用的过程中稍微对文档进行了说明。 使用jni-rs库既然rust作为库,那java端就是使用者。所以一切使用以java端出发。先编写一个HelloWorld.java文件如下 1234567891011121314class HelloWorld { private static native String hello(String input); static { System.loadLibrary("mylib"); } // The...
从零构建一个SPV钱包其一
从零构建一个SPV钱包其一开篇这是如何从零开始构建一个SPV钱包的开篇文章的第一篇,按照行文习惯,先列出系列文章的目的: 构建一个SPV钱包,确切的说是一个BTC的SPV钱包 在区块链世界中,去中心化一直是核心话题,实际上市面上很多钱包是有后端的,或者说有后端支援。出于种种目的,他们的钱包并非完全去中心化。但是BIP37给比特币提供了一个去中心的提案。本文的全部方案均起源于BIP37 https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki BIP37是一切的起点,所以阅读本片文章的开端必然需要阅读BIP37。 准备在正式开始之前,还需要预先的准备知识。因为不是知识普及型的文章,所以不准备介绍基本概念。但是需要提供的基本的知识会提到 首先会搭建BTC节点关于如何搭建btc节点的文章很多,不列出。本文中使用过的节点版本为v0.18,其他稳定版本均可。使用环境为乌班图。一切以可以稳定运行比特币节点为主。它属于基础准备知识,并非重点。关于如何配置节点,可参考我的博文 比特币客户端设置 比特币节点远程访问 搭...
rust工程实践
rust工程实践本文是rust的实践记录,主要用来记录rust写工程代码,和在tikv的talent-plan中学习到的代码常识。这里列出的是比较重要,但是不足以写一篇文章来讨论的。长期更新。以后考虑加个目录方便查询。 在写lib的时候,直接建立(在src下)bin文件夹,bin文件下的东西无需在lib.rs中声明就可以使用。且bin文件夹下的rust文件无论怎样命名,在文件中只要有fn main()就可以直接运行。也无需在Cargo.toml文件中进行特殊声明。在murmel和talent-plan中已经证明这一点。 想要进行测试,请在src的同级目录下建立一个tests文件夹(注意拼写,必须是tests)。然后就可以使用cargo test命令。 [dev-dependencies] 适用于tests example benchmarks。正式构建的时候不会用到这个 注重测试,因为测试定义了什么是正确行为。所以阅读源码也要看测试 Re-export技巧。假定我们有一个lib kvs。目录为kvs/src/lib.rs 在lib中定义了mod kv。另有文件夹kvs/s...
记录一次烦人的编译出错问题
记录一次烦人的编译问题,因为这个过程可以能可能会对以后解决类似问题有一定的参考性,特地做个记录。 我想做什么我之所以要做这个,是因为我想借用murmel库,在murmel基础上拓展功能。其中murmel的消息类型定义在rust-bitcoin库中。为了拓展功能,我准备先fork rust-bitcoin魔改rust-bitcoin,加我想要的消息。然后fork murmel,魔改murmel外带让murmel依赖我修改过的rust-bitcoin。 听起来有点像把大象放冰箱需要几步。是的,我先改rust-bitcoin(这个库是序列化比特币消息的),然后我修改murmel,让他依赖改过的rust-bitcoin。最后我得到一个可以用的SPV节点。完工! 我遇到了什么问题先魔改rust-bitcoin。这个很顺利。然后fork了murmel,然后编译不过。此处应该有编译错误(但我不想列出来),总体意思是说有的类型 Hash 没有实现serde的部分trait。 我的折腾过程这个问题很奇怪,我之前git clone的版本是可以编译的,而且看提交记录这个项目这几个月并没有更新。然后...
SPV节点获取merkerblock数据
在之前的文章中提到了SPV节点,一直说要写文章说明是什么是比特币SPV节点。网上有很多文章来描述这个问题,我之前也写过相关的文章,有兴趣的话可以回去查阅相关问题。简单来说,SPV**节点最主要的特点就是:只存储头信息(BlockHeader)。**所以他做到了存储数据规模大幅减少,只有完整数据的千分之一的水平。所以SPV节点适合在存储有限的设备上运行,比如手机客户端。但是本文的重点不是重复讲述SPV节点的概念的,而是换一个角度,从比特币网络协议入手,描述如何从全节点下载SPV所需的数据到节点上(SPV节点上)。这个所需的的信息,就是merkerblock。 本文的关键字是:”SPV节点”,”比特币网络协议”,”BIP47” 交易的基本问题在探讨如何和比特币网络进行信息交互之前先解释一个基本问题 实现比特币交易的形式有哪些? 虽然如此描述这个问题并不准确,但我还是按照自己的理解去解答这个问题,同时参照以上的图片来辅助说明。实现交易的形式有两类 借助于比特币全节点 借助于比特币的SPV节点 对于1,很明确。比特全节点有区块链完整的信息。获取任何交易信息,发起交易和广播不在话下...
如何给过长数组实现Debug
更新:rust在2021年实现了const generics。以下的问题不会存在了。 在rust中,我们可以很方便的用Derive给结构体实现Debug宏(是编译器自动实现的),但是编译器给数组实现的Debug只有长度在32以下的,要是超过32位就得自己实现了。所以出现了本文的问题 如何给过长数组手动实现Debug Trait。一番尝试之后,发现可以这样 1234567891011121314151617use std::fmt;struct Array<T> { data: [T; 1024]}impl<T: fmt::Debug> fmt::Debug for Array<T> { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.data[..].fmt(formatter) }}fn main() { let array = Array { data: [0u8; 1024] }; ...
周报,软件构建和职业发展
吾日三省吾身 ——《论语·学而》 距离上次频繁发布文章,已经过去一个多月了。这一个多月以来,我非常认真的研究关于取款链交易和SPV节点相关的问题。今日又听闻leader关于自己软件生涯的反思和总结。leader开发生涯漫长,反思亦有重大价值,故作文。 在软件开发过程中,几乎每家公司都有写周报的要求,管理粒度更细化的公司还要要求日报。要求详细回报每日、每周的工作情况。周报从公司和项目leader的角度来说,他可以监控开发人员的开发情况,对于KPI管理也有较大作用。但是多数时候我们是怎么对待周报的呢:觉得周报是对公司的交代,对领导交代?每周的周报在周末快下班的时候草草了事?我想这是普遍现象。 其实周报最大的意义是关乎我们自身的。周报的最大意义是对于我们工作的总结和预估。不知道读者读过柳比歇夫那本《奇特的一生》吗?那本的书所宣扬的思想并不复杂,就是精确地统计自己每日工作时间。然后每日总结,看自己那些时间是低效浪费的,加以改进。时间统计法最大的原则就是诚实。吃饭喝水,哪怕是工作时间划水也要如实记录。Timelog和周报的区别就是,Timelog完全是对自己负责,写周...
Rust关于数据溢出安全
在4个多月之前,也就是19年的7月份。在大佬的推荐下,有幸拿到了今日头条的面试机会。在漫长的面试过程中,头条的面试官态度热情,问的问题兼具广度和深度。再很多问题回答的一塌糊涂的条件下,也让我面试了长达五小时。特别的最后的面试官,态度友好且诚恳,对我的诸多不足之处提出委婉的建议。有这样的面试体验是非常棒让我获益良多,在此表达我的感谢之情。不过本篇文章不是讲述面试经验或者体会的,是讲面试中被反复提到的问题: Rust数据计算溢出怎么办? 因为面试的是cpp/rust相关的岗位,面试官提出这个问题之后我是很懵的。以为之前完全没考虑过这个问题。Rust号称安全,那么他是如何处理这个问题的呢。当时我的回答是:换用更大的数据类型。其实当时这个回答说出口,就觉得完全不对,毕竟int32之上还有int64,无论用多大的数据类型,计算依旧可能溢出。 我想今天我可以很好的回答这个问题。在c语言中,无符号整数完全不会溢出(overflow),因为数据一旦超过上限,则自动舍弃高位数据。对于有符号数,一旦超过上限,则标准这是ub。Rust号称安全,从设计上就要尽可能的避免ub,对于数据溢出,也算是语言...