占星与星座计算 天球
占星与星座计算 天球最近因为某些原因,有了一段空余的时间。当你空闲便有了一些奇思妙想。因为很多年前特别喜欢一个关于星座的故事,所以利用这一段空余时间写一个系列文章讲占星中的一个小知识。为了不使文章引起争议,特此声明:本人完全相信星座!不解释。文章的前面系列介绍和占星有关的天文基本概念,后面具体根据人的出生时间,地理位置(经纬度)来计算人的星座。可能读了这一系列的文章,大家可以更好的理解为什么星座归类于“占星学”,这样一个听起来非常正式的名字。另外因为不是撰写论文,本文不会详细列出各类依据。太累! 天球概念 以上图片为完整的天球示意图 和地球概念相对,古代天文学家提出了天球的概念。天球是一个想想的球体,他也是旋转的。理论上具有无限大的半径且和地心是同心的。如图所示:和地球有赤道和南北极的概念对应,天球也有对应的天球赤道和天球南北极。 古代天文学家认为我们和星体是等距离的,尽管这并不正确。因为古代缺乏有效的天文观测手段。星球不是靠我们肉眼就可以判断出距离的。古代科学家克服了这种距离上的因素,使用角度来确定星球在天空中的位置。在当时观测条件受限的情况下,不失为一种很有效的天文抽象系统。...
比特币pow难度验证
比特币pow难度验证何为POWpow的全称为proof of work,即工作量证明。简单的解释为“做了多少工作”。抛开区块链的背景,pow就是对自己做了多少工作的一种说明:比如做了学习了50个小时的汽车驾驶。而他人很容易验证这个结果:你可能50个小时之后拿到了一本驾照。别人就知道你确实在学习驾驶上使用了50个小时。 Block Header在区块链的世界里,pow的数据可以体现在区块链的区块头中。当然一般来说,讲解POW的难度离不开挖矿问题。本文因为主要讨论方向的问题,不展开讲挖矿,主要从区块头入手。在阅读下面的内容之前,默认读者已经有了如下前置知识 区块链常识 比特币基本概念 挖矿基本概念 抛开前置知识之后,我们来看区块头的数据结构。 https://en.bitcoin.it/wiki/Protocol_documentation#Block_Headers 可以直接参考以上链接,当然可以可以直接查看比特币的源码,我们现在把数据列出来。 12345678struct header_structure { // BYTES NAME uint32_t nVe...
拜占庭将军问题简述
拜占庭将军问题简述拜占庭的简述本文将用于介绍著名的拜占庭将军问题。在介绍拜占庭将军问题之前,先简单说一下拜占庭。拜占庭帝国,在古代西欧也被称之为东罗马帝国。是一个位于欧亚交界处的封建君主制国家,其领土包括现在的欧洲南部,西亚和北非。公元四世纪左右,罗马帝国开始分列为罗马东部和罗马西部,这两个国家都被视为罗马正统,大概到公元十世纪,罗马西部陷落,随着神圣罗马帝国的建立,罗马东部失去了罗马这个单词的独占权,开始被称之为东罗马帝国。大概在16世纪之后,开始出现了拜占庭帝国的说法。值得一提的是,拜占庭帝国的首府君士坦丁堡被第四次十字军东征攻陷,从此一蹶不振。1453年5月29日,君士坦丁堡被强大的奥斯曼帝国攻陷,末代皇帝君士坦丁十一世战死。东罗马帝国就此终结。当然,此文不是介绍东罗马帝国历史的文章,在此仅简述拜占庭帝国的历史。 拜占庭将军问题是什么拜占庭将军问题和拜占庭的历史其实并无关联,拜占庭将军问题也不是历史上真实存在的问题,他是著名计算机大神兰伯特于1982年提出的。拜占庭问题描述的是如下的场景 假设有一座城堡,拜占庭帝国想攻陷这座城堡。所以派出了很多支军队,因为通讯条件很落后,...
在M1上编译substrate
之前已经在x86的mac电脑上编译过substrate,按照官方指南上的操作就可以正常编译。但是在新款m1电脑上并没有编译通过,现在重新尝试在m1上编译substrate。 主要的准备过程参考如下文章 https://zhuanlan.zhihu.com/p/337224781 不过参考文章写于2020年12月16日,到现在(2021年3月10日)有部分状况已经发生了变化。针对和文章中不一样的状况稍作说明。 RUSTrust环境现在可以直接支持m1。所以使用rustup脚本可以直接安装rust,不需要额外设置。安装完成之后使用 rustup show 查看toolchain。则会发现是以aarch64开头的,原来的x86下面的tool-chain是 stable-x86_64-apple-darwin (default) 注意差别。 brewmac上的包管理离不开brew,所以一定需要安装brew。brew现在也已经官方支持m1,不再需要像参考文章中的特殊设置,直接使用官方脚本安装即可。brew在mac下有两个目录,我们暂时只关心在m1下的原生文件目录。可以cd到一下目录...
sqlite自增小知识
Sqlite自增字段起因:在使用数据库存储从区块链网络上取来的block_header时,block_header本身并不带自身的高度信息。不过取来的数据是经过筛选的,按照数据库存储的顺序就可以代表blockheader的高度。所以在数据库中增加一个id primiry key autoincrement 的自增主键。每次从数据库查询时获取id值来代表区块的高度。但后来重构,id被TEXT类型的逐渐替代,所以这个功能无法正常实现。所以产生以下疑问 在已经有TEXT类型的主键后,sqlite可以拥有别的自增字段吗?不可以!在sqlite的文档FAQ中第一个问题(文末给出参考链接)就是关于如何设置自增字段的。在sqlite中自增约束AUTOINCREMENT只可以跟在PRIMARY KEY后面。把AUTOINCREMENT放在主键以外的地方是不可以的。或者再明确一点,要想在sqlite中拥有一个自增字段必须这样写 1id INTEGER PRIMARY KEY AUTOINCREMENT, 要求id的类型必须是INTEGER。每次插入数据库的时候,不要插入id的数据,数据库会自动为...
多线程原语ConVar
多线程原语CondVar多线程下的原语,除了我们常用的锁,还有另外一类用于同步的原语叫做“屏障”,“条件变量”(在rust或者cpp中)。在其他语言中也有类似的概念,叫做栅栏,闭锁,屏障,信号量等。他们具有相同的意义。 在介绍条件变量之前,先介绍屏障(Barrier)。屏障相当于一堵带门的墙,使用wait方法,在某个点阻塞全部进入临界区的线程。条件变量(Condition Variable)和屏障的语义类似,但它不是阻塞全部线程,而是在满足某些特定条件之前阻塞某一个得到互斥锁的线程。 单纯讲条件变量的意义并不直观。换种描述 条件变量可以在我们达到某种条件之前阻塞线程,我们利用此特性可以对线程进行同步。或者说做到按照某种条件,在多个线程中达到按照特定顺序执行的目的。 为此我们设计如下下面流程。为此流程写一段代码,来体会条件变量的作用 我们启动三个线程,t1,t2,t3。分别执行任务T1,T2,T3。现在要求:T2必须等待T1和T3完成之后再执行 12345678910111213141516171819202122232425262728293031323334353637...
Jni符号对照
Jni符号表本文是之前博客文章 《使用rust写安卓库》 的延续。之前的文章主题是如何利用rust-jni库提供便于java使用的rust jni代码。本文在之前的基础上继续提供后续关于jni符号,或者type的说明。 起因写rust端代码的时候,如果我们想返回一个java端的对象我们的rust代码大概会按照以下写法(仅为示例,不可运行): 12345678910111213141516#[no_mangle]#[allow(non_snake_case)]pub extern "system" fn Java_JniApi_hello(env: JNIEnv, _: JClass, str: JString) -> jobject { let str = env.get_string(str).unwrap(); let message_class = env.find_class("JniApi$StatusMessage").expect("can't find class JniApi$StatusCode"); let message_ob...
比特币是不是货币?
比特币是不是货币今天晚上和人聊天的时候,提到的了这个话题。我开始从事比特币相关开发也有一段时间了,经常有人会提到这个话题。这个话题比”比特币是什么?”更加具体,我也被问到过多次。本着不重复劳动的初心,特意写这篇小文章来说说我的理解。 回答是否定的,比特币并非货币。 严格的来讲,比特币是一种数字通证。或者从技术角度来讲我们把这类东西都统称为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...