<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>技术 on 涯余的博客</title><link>https://hangyan.github.io/categories/%E6%8A%80%E6%9C%AF/</link><description>Recent content in 技术 on 涯余的博客</description><generator>Hugo</generator><language>zh</language><managingEditor>hang.yan@hotmail.com (涯余)</managingEditor><webMaster>hang.yan@hotmail.com (涯余)</webMaster><lastBuildDate>Thu, 23 Jul 2020 16:32:10 +0000</lastBuildDate><atom:link href="https://hangyan.github.io/categories/%E6%8A%80%E6%9C%AF/index.xml" rel="self" type="application/rss+xml"/><item><title>BlueTrace与健康码</title><link>https://hangyan.github.io/post/2020-07-23-blue-trace/</link><pubDate>Thu, 23 Jul 2020 16:32:10 +0000</pubDate><author>hang.yan@hotmail.com (涯余)</author><guid>https://hangyan.github.io/post/2020-07-23-blue-trace/</guid><description>&lt;p&gt;疫情之下，各国都在不断地调整自己的防疫政策。中国的模式已经证明了其可能是最有效的方式之一，但因为种种原因大部分国家难以效仿和接受。从技术层面来讲，基于支付宝/微信等国民APP之上的健康码模式也是如此:有效，但是别国难以效仿。新加坡最开始使用&lt;code&gt;BlueTrace&lt;/code&gt;协议并开发出了相应App让国民下载使用,部分其他国家也开始效仿，甚至有望能成为一种国际通用的防疫标准。&lt;/p&gt;
&lt;p&gt;隐私保护是 BlueTrace 所考虑的最主要特点之一。其手段包括如下方面:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;尽可能少的收集用户信息，卫生部门唯一收集的信息是手机号&lt;/li&gt;
&lt;li&gt;本地存储用户接触记录，只有当被感染者愿意分享此数据时卫生部分才能获取&lt;/li&gt;
&lt;li&gt;第三方无法通过此协议一直追踪用户。因为相关标识ID会一直更换&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以在对用户的标识方面，主要是通过算法生成的 UserID 和 TempID 来进行。当用户用手机号进行注册时,后台服务会生成一个 UserID, 而用户在互相接触需要通过蓝牙交换信息时，则通过 TempID 进行。TempID的 大概结构如下:&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://hangyan.github.io/images/posts/bluetrace/tempid.png"&gt;&lt;/p&gt;
&lt;p&gt;可以看到其有如下特点:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;加密。只有卫生部门才有密钥能解密数据&lt;/li&gt;
&lt;li&gt;过期时间。TempID有过期时间，一般在15m左右.这样可以尽量减少恶意攻击或者伪造假数据&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;TempID的生成需要联网(加密啥的)，所以为了考虑到用户不联网的情况，所以TempID可以一次性尽量生成多个，在联网的时候一次性发给用户以备用。&lt;/p&gt;
&lt;p&gt;当装有相应APP的用户相遇时，设备会通过 Bluetooth Low Energy (BLE)协议进行通信并交换信息，其数据流程如图所示:&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://hangyan.github.io/images/posts/bluetrace/ble-handshake.png"&gt;&lt;/p&gt;
&lt;p&gt;这里面两个 Device 分别有一个角色定位，一个叫 Central ，一个叫 Peripheral。Central 主动扫描 Peripheral 并读取其信息，然后返回一些额外信息。一个手机一般是按一定时间比率轮换在两个角色之间切换。其交换的数据大概如下所示:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;id&amp;#34;: &amp;#34;FmFISm9nq3PgpLdxxYpTx5tF3ML3Va1wqqgY9DGDz1utPbw+Iz8tqAdpbxR1 nSvr+ILXPG==&amp;#34;, // TempID
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;md&amp;#34;: &amp;#34;iPhone X&amp;#34;, // Device model
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;rc&amp;#34;: -60, // Signal strength
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;o&amp;#34;: &amp;#34;IJ_HAI&amp;#34;, // Health authority identifier
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;v&amp;#34;: 2 // Protocol version
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里面需要注意的是:&lt;/p&gt;</description></item><item><title>代码与注释</title><link>https://hangyan.github.io/post/2019-07-14-code-and-comments/</link><pubDate>Sun, 14 Jul 2019 21:14:49 +0000</pubDate><author>hang.yan@hotmail.com (涯余)</author><guid>https://hangyan.github.io/post/2019-07-14-code-and-comments/</guid><description>&lt;!-- toc --&gt;
&lt;p&gt;代码应该拥有良好的注释一直是业界共识，毕竟，在可预见的未来里，阅读代码的主要还是人。所有的语言都支持注释，有的拥有额外的注释提取工具及格式规范。但总体来说，大部分语言在这块做的都比较一般。Python有一些约定俗称的规范以及 Sphinx 这样的工具， Golang 的规范比较简单，但内置了 godoc 工具。Lisp 算是做的比较好的，示例如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-lisp" data-lang="lisp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt; &lt;span class="nv"&gt;small-prime-number-p&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s"&gt;&amp;#34;Return T if N, an integer, is a prime number. Otherwise, return NIL.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;cond&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nb"&gt;or&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="no"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;divisorp&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;t&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;loop&lt;/span&gt; &lt;span class="nv"&gt;for&lt;/span&gt; &lt;span class="nv"&gt;i&lt;/span&gt; &lt;span class="nv"&gt;from&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="nv"&gt;upto&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sqrt&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;by&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;never&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;divisorp&lt;/span&gt; &lt;span class="nv"&gt;i&lt;/span&gt; &lt;span class="nv"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其独特之处在于，不同于一般语言注释位于函数体之外，而是将其放置于函数 body 开始处。这样开发者更容易将其当作函数定义的一部分，也有助于养成良好的注释习惯。&lt;/p&gt;
&lt;p&gt;Golang 虽然 在注释方面做的普通，但是在官方 library 以及最佳实践方面成功地鼓励了人们尽可能地写非常详细的注释，具体到一个 struct 的各个字段上。尤其是在 kubernetes 社区里面, 其&lt;a href="https://news.ycombinator.com/item?id=18772873"&gt;Space Shuttle style&lt;/a&gt; 的 Code 对于社区的蓬勃发展可以说是一个极大的背后功臣，从如下的代码便可一窥其风格：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Adapts a ConfigMap into a projected volume.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// The contents of the target ConfigMap&amp;#39;s Data field will be presented in a&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// projected volume as files using the keys in the Data field as the file names,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// unless the items element is populated with specific mappings of keys to paths.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Note that this is identical to a configmap volume source without the default&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// mode.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ConfigMapProjection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;struct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;LocalObjectReference&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// If unspecified, each key-value pair in the Data field of the referenced&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// ConfigMap will be projected into the volume as a file whose name is the&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// key and content is the value. If specified, the listed keys will be&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// projected into the specified paths, and unlisted keys will not be&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// present. If a key is specified which is not present in the ConfigMap,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// the volume setup will error unless it is marked optional. Paths must be&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// relative and may not contain the &amp;#39;..&amp;#39; path or start with &amp;#39;..&amp;#39;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// +optional&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Items&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="nx"&gt;KeyToPath&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Specify whether the ConfigMap or it&amp;#39;s keys must be defined&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// +optional&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Optional&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可读性越好的代码越容易流行。Golang 在这方面做的很好。&lt;/p&gt;</description></item><item><title>如何防止代码变成 SHIT</title><link>https://hangyan.github.io/post/2019-05-01-great-code/</link><pubDate>Wed, 01 May 2019 19:03:04 +0000</pubDate><author>hang.yan@hotmail.com (涯余)</author><guid>https://hangyan.github.io/post/2019-05-01-great-code/</guid><description>&lt;!-- toc --&gt;
&lt;p&gt;最近发现之前写过的很多项目，不管是 python/go/cpp 的，最终回看起来代码都变的很难看，尤其是多人合作的时候。
这是一个很头疼的问题。自己平时很在意这个，但是代码最终确都变成了 shit。&lt;/p&gt;
&lt;h2 id="问题"&gt;问题&lt;/h2&gt;
&lt;p&gt;当一个人开发的时候，问题主要在于一个人的自律性不够强，不管是代码注释等都是随意写的，即使偶尔意识到了问题，但也难以保证能一直坚持下去。
而当人多的时候，问题经常处在多人风格的不同上。如果没有&lt;code&gt;工具&lt;/code&gt;来强制大家遵守一定的规则，那么大家每个人自己的风格放在一起的时候，就成了垃圾代码。
避免代码变成 shit 的唯一方法，就是让大家写的代码&lt;code&gt;看起来都一个样&lt;/code&gt;。而这个工作除了由开发人员的 Code Review 之外，还需要工具来约束。&lt;/p&gt;
&lt;h2 id="解决方法"&gt;解决方法&lt;/h2&gt;
&lt;h3 id="cicd"&gt;CI/CD&lt;/h3&gt;
&lt;p&gt;最开始接触 CI/CD，我只是认为它主要是用于部署方面的一个工具。现在发现，它对于代码质量的改进也是意义巨大的。所有代码通用规范上的约束，静态分析，复杂度分析等都可以通过自动化工具来执行。
一方面，我们可以组合尽可能多的代码静态分析工具，来约束提交代码的错误，提供代码改进的建议，形成统一的代码风格。另一方面，最于 Code Review 来说，不再需要关注基本的代码风格以及基础部分，而只用关注于具体的业务以及代码架构层面的问题。&lt;/p&gt;
&lt;h3 id="静态分析"&gt;静态分析&lt;/h3&gt;
&lt;p&gt;Python 这样的代码，在多人合作的大型项目上，如果没有非常严格的代码约束，最终出来的项目时非常难以维护的。可能经常部署出来的代码连跑都跑不起来。相对来说，静态类型语言在这方面的优势是巨大的，编译器在编译代码阶段能发现大多数比较明显的问题，最终线上的问题一般都是需要人来参与分析的。&lt;/p&gt;
&lt;p&gt;代码的静态分析是一个非常古老但是重视程度不够的技术。静态类型语言的代码分析技术能够极大地减少代码中可能存在的 bug,并给出很多的建议。以 Golang 为例，目前已经有几十款静态分析工具。
而像&lt;a href="https://github.com/golangci/golangci-lint"&gt;golangci-lint&lt;/a&gt;这样的工具，可以将多种分析工具结合起来，在各个层面给出代码改进的建议。比如：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;代码的简化写法&lt;/li&gt;
&lt;li&gt;可能的 bug&lt;/li&gt;
&lt;li&gt;Dead Code&lt;/li&gt;
&lt;li&gt;未使用的或者被覆盖的变量&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;SonarQube 其实是类似的产品，只不过是 Client/Server 的架构，提供了诸如复杂度分析，单元测试覆盖率等指标。良好的 UI，以及插件式的架构，与普通的 cli 工具结合起来之后，对于代码质量的提高是非常有益的。&lt;/p&gt;
&lt;p&gt;总之，工具能处理的事情越多，人的精力就更多的能去关注更上的层面和业务层面。&lt;/p&gt;
&lt;h3 id="code-review"&gt;Code Review&lt;/h3&gt;
&lt;p&gt;Code Review 虽然成为一个共识，但真正的效率确实难以保证的。莫名其妙的改动，形式化的 approve,现有工具的局限等等问题都造成了参与的人在这方面的低效率。所以总是需要有各种规范来指导人们如何进行 Code Review。一般来讲，我们可以将代码的改动拆分为三个问题&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Why? 为什么要做这个改动&lt;/li&gt;
&lt;li&gt;How? 怎么做这个改动&lt;/li&gt;
&lt;li&gt;What? 具体做了哪些改动。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这几个问题，工具能参与的只是&lt;code&gt;What&lt;/code&gt;的一部分。其他的部分都需要人来 review。一般的 Code Review 提交的模板也都要求提交 PR 的人尽量说清楚 Why,通过文档 link 或者文字等形式。具体的 How 以及 What，则需要具体的人来参与 review。&lt;/p&gt;</description></item><item><title>Namecoin</title><link>https://hangyan.github.io/post/2017-08-22-namecoin/</link><pubDate>Tue, 22 Aug 2017 00:00:00 +0000</pubDate><author>hang.yan@hotmail.com (涯余)</author><guid>https://hangyan.github.io/post/2017-08-22-namecoin/</guid><description>&lt;!-- toc --&gt;
&lt;p&gt;互联网到今日已经越来越趋向于中心化，用户的隐私安全以及大公司的行为也日渐引起担忧。去中心化网络是一个应对此问题的重要思想，blockchian,bitcoin,tor 等都是一些具体的技术探索，很多已经有了越来越大的影响力。Namecoin 也是其中的一个。&lt;/p&gt;
&lt;p&gt;Namecoin 想要解决的是目前 DNS 存在的一些问题。中央机构控制的 DNS 很容易因为各种原因受到干扰，用户的利益和隐私容易受到侵犯。Namecoin 借助于 bitcoin 的思想，构建了一个去中心化的 DNS 系统。&lt;/p&gt;
&lt;h1 id="zookos-triangle"&gt;Zooko&amp;rsquo;s triangle&lt;/h1&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://upload.wikimedia.org/wikipedia/commons/thumb/5/5c/Zooko%27s_Triangle.svg/440px-Zooko%27s_Triangle.svg.png"&gt;&lt;/p&gt;
&lt;p&gt;类似于分布式系统中的 CAP 理论。类似 DNS 这样的协议，我们期望它具有的三个特性很难满足: 安全,可读性好,去中心化。目前的最常用的 DNS 系统不满足去中心化。DNSSec 对现有的 DNS 做了一些安全性的增强，但仍然是中心化的。&lt;code&gt;.onion&lt;/code&gt;和&lt;code&gt;bitcoin&lt;/code&gt;是去中心化的和安全的，但是可读性很差等等。&lt;/p&gt;
&lt;p&gt;Namecoin 是满足上面要求的一个系统。（&lt;code&gt;Aaron Swartz&lt;/code&gt;曾经提出过这样的设计思路)&lt;/p&gt;
&lt;h1 id="namecoin"&gt;Namecoin&lt;/h1&gt;
&lt;p&gt;Namecoin 基于 BitCoin,本身就是在 Bitcoin 的代码上实现的(大概做了 400 多行改动)。挖矿的方式跟 bitcoin 一样，只是用的是不同的 block chain.二者的目的不同,bitcoin 主要还是为了成为一种货币系统，Namecoin 是为了成为一种命名系统。所以二者的关注点不同，blockchain 分开也是最合理的。二者有一些不同的规则：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;namecoin 要求名字的唯一性(域名)，而 bitcoin 不要求&lt;/li&gt;
&lt;li&gt;经济交易以及域名注册使用的货币大小不一样，block size 设的不一样更好&lt;/li&gt;
&lt;li&gt;通货膨胀对 bitcoin 的影响很大，namecoin 则不一样。&lt;/li&gt;
&lt;li&gt;namcoin 中，注册域名需要花钱,但这些货币会被销毁(0.01NMC).因为是去中心化的系统，没有收费的中央系统。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Namecoin 里的数据主要分为两种 domain name 和 NameID&lt;/p&gt;
&lt;h2 id="domain"&gt;Domain&lt;/h2&gt;
&lt;p&gt;Domain 的格式类似于:&lt;/p&gt;</description></item><item><title>Blockchain</title><link>https://hangyan.github.io/post/2017-08-12-blockchain/</link><pubDate>Sat, 12 Aug 2017 21:37:39 +0800</pubDate><author>hang.yan@hotmail.com (涯余)</author><guid>https://hangyan.github.io/post/2017-08-12-blockchain/</guid><description>&lt;!-- toc --&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2017-08-12-blockchain/#%e4%bb%8b%e7%bb%8d"&gt;介绍&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2017-08-12-blockchain/#%e5%8c%ba%e5%9d%97%e7%bb%93%e6%9e%84"&gt;区块结构&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2017-08-12-blockchain/#%e5%a4%b4%e7%bb%93%e6%9e%84"&gt;头结构&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2017-08-12-blockchain/#%e5%8c%ba%e5%9d%97%e7%bb%93%e6%9e%84-1"&gt;区块结构&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2017-08-12-blockchain/#%e5%88%9b%e4%b8%96%e5%8c%ba%e5%9d%97"&gt;创世区块&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2017-08-12-blockchain/#%e5%88%86%e5%8f%89"&gt;分叉&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2017-08-12-blockchain/#proof-of-work%e5%b7%a5%e4%bd%9c%e9%87%8f%e8%af%81%e6%98%8e"&gt;Proof-of-work(工作量证明)&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2017-08-12-blockchain/#%e9%82%ae%e4%bb%b6-header"&gt;邮件 Header&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2017-08-12-blockchain/#bitcoin"&gt;Bitcoin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hangyan.github.io/post/2017-08-12-blockchain/#ref"&gt;REF&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- tocstop --&gt;
&lt;h1 id="介绍"&gt;介绍&lt;/h1&gt;
&lt;p&gt;区块链是由一串使用密码学方法产生的数据块组成的，每一个区块都包含了上一个区块的哈希值(hash),从创始区块(genesis block)开始连接到当前区块，形成块链(类似数据结构中的链表).每一个区块都确保按照时间顺序在上一个区块之后产生，否则前一个区块的哈希值是未知的。&lt;/p&gt;
&lt;p&gt;其优势在于:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;完全分布式的，无中心节点(单点故障)&lt;/li&gt;
&lt;li&gt;任何节点都可以创建交易。在经过一段时间的确认之后，就可以合理地确认该交易是否有效。&lt;/li&gt;
&lt;li&gt;修改交易记录的成本非常高&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;区块链也是比特币等技术的基础。它也是一种非常重要的新思想，促使人们对现有的网络,社会,经济等进行重新思考。&lt;/p&gt;
&lt;h1 id="区块结构"&gt;区块结构&lt;/h1&gt;
&lt;h2 id="头结构"&gt;头结构&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;大小(bytes)&lt;/th&gt;
&lt;th&gt;字段&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;版本&lt;/td&gt;
&lt;td&gt;版本号&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;父区块哈希值&lt;/td&gt;
&lt;td&gt;引用区块链中父区块的哈希值&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;merkle 根&lt;/td&gt;
&lt;td&gt;该区块交易的 merkle 树根的哈希值&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;时间戳&lt;/td&gt;
&lt;td&gt;该区块产生的近似时间(精确到秒的 unix 时间戳)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;难度目标&lt;/td&gt;
&lt;td&gt;该区块工作量证明算法的难度目标&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Nonce&lt;/td&gt;
&lt;td&gt;用于工作量证明算法的计数器&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="区块结构-1"&gt;区块结构&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;大小(bytes)&lt;/th&gt;
&lt;th&gt;字段&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;区块大小&lt;/td&gt;
&lt;td&gt;该字段之后的区块大小&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;区块头&lt;/td&gt;
&lt;td&gt;区块头结构 (上面的大小之和)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1-9&lt;/td&gt;
&lt;td&gt;可变整交易计数器&lt;/td&gt;
&lt;td&gt;交易的数量&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;可变&lt;/td&gt;
&lt;td&gt;交易&lt;/td&gt;
&lt;td&gt;记录在区块里的交易信息&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="创世区块"&gt;创世区块&lt;/h2&gt;
&lt;p&gt;比特币区块链的第一个区块，创建于 2009 年，我们称之为创世区块。它是比特币区块链里所有区块的共同祖先，这意味着你从任一区块，循链向后回溯，最终都将到达创世区块。每一个节点都“知道”创世区块的哈希值、结构、被创建的时间和里面的一个交易。因此，每个节点都把该区块作为区块链的首区块，从而构建了一个安全的、可信的区块链的根。&lt;/p&gt;</description></item></channel></rss>