知行合一

致良知


  • 首页

  • 归档

  • 站点地图

bitcoin交易网站实现

发表于 2018-08-30 |

选型

  • c/c++ 语言,bitcoin最核心的版本是用c/c++实现,但由于最初版本源码结构太差,现在比以前好了很多,但还是在继续调整。由于c/c++语言本身的问题,库引入都是比较麻烦的事情。它的有点相对其他实现比较稳定

  • golang语言,有bitcoin的实现btcd,但最近没有更新,有些bip也没有实现;另外有开发者尝试用golang实现的例子,如这个,这个,借鉴的内容会多一些。

其他如js,但并不是个人擅长,也不是区块链的核心语言系列,就不考虑。上面两种选哪种都ok,看个人擅长,这边就选择使用golang。

接口选择方面,直接调用bitcoin core的rpc接口或者使用blockchain.com的api。这里选择了第一种。

实现方法

一般来说要实现交易所或者交易网站的功能,要实现三块功能:地址管理、充值、提现

  • 地址管理

    • 目标:
      • 方便管理用户的地址
      • 保存好私钥的安全性
    • 实现:
      • 一般来说使用HD钱包的方式生成地址
      • 地址类型一般用着两种:P2PKH和p2sh-p2wpkh,后台生成用统一用一种即可,第二种打包费用更低
      • 公钥和私钥都使用压缩格式
      • 私钥的存储需要隔离,有几个维度
        • 存储的数据库要独立
        • 对数据库中的内容需要加密
        • 启动的时候,从root启动,解密私钥的秘钥从环境变量读取或者从文件读取(启动完成后把文件删除)
  • 充值

    • 目标:
      • 玩家充值:玩家充值后,应立即感知到充值行为
        • 充值到某个帐号,就无法识别出是哪个玩家进行了充值,所以需要对每个帐号生成一个区块链地址,玩家向这个地址充值
      • 充值服务可随时更新
    • 实现:
      • 用一个goroutine监控交易池,一旦发现交易池中有游戏中玩家的对应地址,就记录玩家充值状态到缓存,设置超时60分钟;遍列过的交易不再重复查看
      • 用一个goroutine监控[1,3)个确认的区块,如果发现其中有玩家的对应地址,就记录玩家充值状态到缓存,设置超时30分钟;遍列过的区块不在查看,遍列过的交易不再重复查看;防止交易池漏查、重启过程中漏查
      • 用一个goroutine监控3个确认以上的区块,如果发现其中有玩家的对应地址,就记录玩家充值状态到数据库;并记录到扫描高度,以防止重启丢失充值记录。
      • 注意点
        • 玩家的充值地址需要同步到内存中,方便快速查找;有新帐号创建的时候,要先同步过来,在创建成功
        • 目前2018-08-30每个区块大约有100-3000个交易不等
        • 交易池中大约有4000+的交易
        • 提取交易信息接口getrawtransaction “txid” ( verbose “blockhash” ) ,需要在bitcoind启动的时候添加-txindex,获取所有的交易索引
    • 风险控制:
      • 软分叉,忽略
      • 硬分叉,使用网络接口监控异常,一旦出现警告,停止服务
        • getnetworkinfo 提取warnings信息
  • 提现

    • 目标:
      • 玩家提现,将中心的对应货币转到链上,且收取一定的手续费用
      • 将玩家的充值,全部转到某个Master帐号上
      • Master帐号充值后,能发现其未使用的UTXO,并录入库
    • 实现:
      • 玩家的提现
        • 发起请求,将玩家的提现请求录入到提现队列,如NSQ,并入库
        • 处理请求,每一个Master帐号对应一个goroutine,每个goroutine从队列中提取请求,处理后发到链上。所有的转账处理的goroutine由Manager goroutine创建,当发现新帐号的时候,立即开启一个新的goroutine
          • 当账户金额不足时,告警
          • 未确认数提现达到一定值时,此账号停止提现
          • 可重发所有请求
        • 确认请求,单独起一个goroutine,监控这些提现行为,达到3个确认后,就同步入库
      • 玩家的充值
        • 单独起一个goroutine,检查充值量和充值额度,当达到一定条件,就将用户的比特币转到一个Master帐号
      • 录入Master帐号的UTXO
        • 单独起一个goroutine,检查Master帐号的充值和玩家的充值的合并,方法跟充值服务的实现差不多

比特币长时间不被确认的处理办法

发表于 2018-08-14 |

原因

  1. 设置了LockTime,交易需要到设置高度或者设置时间才会被打包进入区块

  2. 交易费设置太低,旷工会根据交易费排序,选择交易费高的交易进行打包(老的节点可能会按时间顺序排序),所以会出现两种情况

    • 一直在交易内存池,没有旷工选择打包
    • 交易内存池慢了,或者超时了,被删除掉了

产生上面的这些行为,我们的节点(接受RPC的节点)是无法感知到的,且交易也不会回退,我们用RPC查找的时候,会永远在交易内存池内。

如何处理

  1. 针对1情况,就不要设置LockTime。如果需要设置,一定要核对好。

  2. 针对2情况,有以下几种办法

    • 重启自己的节点,
      • 简单重启,它会重新广播交易,可能再次失败
      • 加-zapwallettxes参数,删除钱包的所有交易记录;加-rescan参数,重新扫描区块链以查找遗漏的钱包交易,获取交易前的UTXO。这个方法不一定能够成功,因为交易可能还在某些节点上。
    • 在btc.com上查找交易是否存在,如果不存在,则用https://btc.com/tools/tx/publish,再次广播交易,可能再次失败;也可以用别家的矿池
    • 打开https://pushtx.btc.com/#/,提供一定的费用,让其矿池打包处理。最长需要4个小时才能进入区块。因为他家的矿池在4个小时内,挖到矿的概率是98%。可能费用比较高。
    • 发送交易的时候,将交易设置成RBF模式(Replace by Fee),允许用高费用交易来替代掉老的交易

在MinGW64下编译obs-text-pango

发表于 2018-08-06 |

obs-text-pango 是什么

首先介绍下OBS是什么,OBS - Free and open source software for live streaming and screen recording(OBS是一款开源的用于录屏直播的工具软件)。旧版的OBS只能支持Windows,目前已经停止开发。作者为了支持Windows/Mac/Linux重写了整个软件,项目地址为obs-studio in Github。

OBS项目的语言分布:

  1. C: 57.6%
  2. C++: 36.3%
  3. Objective-C/Objective-C++: 4%
  4. others: 3%

OBS代码主要包含这些部分:

  1. libobs: 核心代码,定义项目框架以及核心API,主要用C语言编写。
  2. UI: 界面代码,采用C++的QT框架,开发出适用三大平台的界面。
  3. plugins: 插件代码,可独立编译成dll(windows平台)或so(*nix平台),包含Source(录屏输入源)、Output、Service(各种流播服务)等全部被定义为插件。
  4. libobs-d3d11: 基于D3D的图形子系统,主要用在Windows系统。
  5. libobs-opengl: 基于opengl的图形子系统,主要用在*uix系统。

obs-text-pango是obs的一个文本插件plugins,它与obs本身提供的obs-text插件不同之处在于,它支持emoji,且用pango排版引擎实现,项目地址为obs-studio in Github,forked from reboot/obs-text-pango, 这个项目源码需要改进,编译出来是无法使用

如何编译

  1. 使用MSys2的pacman工具安装以下库
1
2
3
4
5
6
7
8
pacman -S mingw-w64-x86_64-pkg-config
pacman -S mingw-w64-x86_64-gcc
pacman -S mingw64/mingw-w64-x86_64-cmake
pacman -S mingw64/mingw-w64-x86_64-make //cp mingw32-make.exe make.exe
pacman -S mingw-w64-x86_64-qt5
pacman -S mingw-w64-x86_64-ffmpeg
pacman -S mingw-w64-x86_64-vlc
pacman -S mingw-w64-x86_64-fdk-aac
  1. 下载obs-text-pango源码
1
git clone https://github.com/kkartaltepe/obs-text-pango.git
  1. 修改CMakeList.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
cmake_minimum_required(VERSION 2.8.12)

project(text-pango)

# Standalone build
if(NOT OBS_OUTPUT_DIR)
#SET(CMAKE_FIND_LIBRARY_PREFIXES "lib" "")
#SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".dll.a" ".lib" ".dll")

set(CMAKE_INSTALL_PREFIX "D:/_workdir/obs/obs-studio/vs2015/rundir/Debug")
list(APPEND CMAKE_INCLUDE_PATH "D:/_workdir/obs/obs-studio/libobs")
list(APPEND CMAKE_LIBRARY_PATH "D:/_workdir/obs/obs-studio/vs2015/libobs/Debug")

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
include(ObsHelpers)

set(CMAKE_C_STANDARD 11)
set(STANDALONE_PLUGIN TRUE)

find_path(OBS_INCLUDE_DIRS
obs-module.h)
find_library(OBS_LIBRARIES
NAMES libobs obs)
# Build as submodule of obs-studio
else()
set(OBS_INCLUDE_DIRS
../../libobs)
set(OBS_LIBRARIES
libobs)
endif()

find_package(Pango REQUIRED)
find_package(Cairo REQUIRED)
find_package(Pangocairo REQUIRED)
find_package(Pangoft2 REQUIRED)
#if(WIN32)
# find_package(Pangowin32 REQUIRED)
#endif()
set(PANGOWIN32_LIBRARIES
"C:/msys64/mingw64/lib/libpangowin32-1.0.a")
find_package(Fontconfig REQUIRED)
find_package(Freetype REQUIRED)

include_directories(
${OBS_INCLUDE_DIRS}
${PANGO_INCLUDE_DIRS}
${CAIRO_INCLUDE_DIRS}
${PANGOCAIRO_INCLUDE_DIRS}
${PANGOFT2_INCLUDE_DIRS}
${FREETYPE_INCLUDE_DIRS})
if(NOT WIN32)
FIND_PACKAGE(PkgConfig)
PKG_CHECK_MODULES(GLIB glib-2.0 REQUIRED)
include_directories(${GLIB_INCLUDE_DIRS})
endif()

link_directories(
${PANGO_LIBRARY_DIRS}
${CAIRO_LIBRARY_DIRS}
${FREETYPE_LIBRARY_DIRS})

set(text-pango_SOURCES
text-pango.c
text-pango.h
text-utilities.h)

set(win32_static_LIBRARIES
intl
fribidi
pixman-1
z
harfbuzz
libpng16
expat
usp10)
if(WIN32)
set(PLATFORM_LIBRARIES ${win32_static_LIBRARIES})
endif()

add_library(text-pango MODULE
${text-pango_SOURCES})
target_link_libraries(text-pango
${OBS_LIBRARIES}
${CAIRO_LIBRARIES}
${PANGO_LIBRARIES}
${PANGOWIN32_LIBRARIES}
${PANGOCAIRO_LIBRARIES}
${PANGOFT2_LIBRARIES}
${FREETYPE_LIBRARIES}
${FONTCONFIG_LIBRARIES}
${PLATFORM_LIBRARIES}) # win only currently
target_compile_definitions(text-pango PRIVATE ${CAIRO_C_FLAGS})


if(STANDALONE_PLUGIN)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_bit_suffix "64bit/")
else()
set(_bit_suffix "32bit/")
endif()
if(APPLE)
install(TARGETS text-pango
LIBRARY DESTINATION "Library/Application Support/obs-studio/plugins/libtext-pango/bin/")
install(DIRECTORY data/common/
DESTINATION "Library/Application Support/obs-studio/plugins/libtext-pango/data")
install(DIRECTORY data/apple/
DESTINATION "Library/Application Support/obs-studio/plugins/libtext-pango/data")
# for packaging, copy all dependencies, change dependency links
# run pkgbuild --identifier user.obsproject.kurufu.text-pango --root ./obs-text-pango-install/ text-pango-mac.pkg
else() # Not apple so normal layout
install(TARGETS text-pango
LIBRARY DESTINATION "obs-plugins/${_bit_suffix}/")
install(DIRECTORY data/common/
DESTINATION data/obs-plugins/text-pango)
# Platform specific data, like fontconfig in win32
if(WIN32)
#install(FILES $<TARGET_PDB_FILE:${PROJECT_NAME}>
# DESTINATION "obs-plugins/${_bit_suffix}/" OPTIONAL)
install(DIRECTORY data/win32/
DESTINATION data/obs-plugins/text-pango)
endif()
endif()
else()
install_obs_plugin_with_data(text-pango data/common)
# calling this twice might not work?
if(WIN32)
install_obs_plugin_with_data(text-pango data/win32)
endif()
if(APPLE)
install_obs_plugin_with_data(text-pango data/apple)
endif()
endif()
  1. 使用window的cmd工具,以x64位的姿态打开,进入obs-text-pango目录,并输入以下命令
1
2
3
4
5
mkdir mingw64
cd mingw64
cmake .. -G "MinGW Makefiles"
make
make install

过程中遇到的问题

  1. 命令行使用msys2_shell.cmd,或者git-bash.exe,会遇到一个sh冲突的问题,所以只能用windows的cmd

  2. cmake的时候使用-G “Visual Studio 14 2015 Win64”,项目能够编译过,且lib也能相互兼容,至少是c的lib,但链接的时候会有各种各样的问题,未深入去研究

  3. cmake的时候使用-G “MSYS Makefiles”,也是各种问题,可能我安装的都是mingw64的库的原因吧

  4. cmake的时候,想尽量静态编译,所以在CMakeLists.txt中加入以下语句,但在链接的时候提示各种各样奇怪问题,所以最后还是去掉

1
2
SET(CMAKE_FIND_LIBRARY_PREFIXES "lib" "")
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".a" ".dll.a" ".lib" ".dll")
  1. 纹理大小为0的时候,会导致程序崩溃,可能是obs新旧版本兼容问题

MinGW开发环境搭建

发表于 2018-08-06 |

类MinGW环境有哪些

  1. MinGW:是Minimalist GNU for Windows的缩写,是让windows开发者可以使用GNU工具链和一些类库,同时也支持win32的api,它编译出来的程序不一定是跨平台的。它有MinGW32和MinGW64两个版本,对应开发32位和64位程序。为了更方便的使用MinGW,就产生了一个叫MSys工具,是一个类Unix命令行环境。由于MSys开发太慢,又搞了MSys2工具,同时还解决了包管理问题,方法是继承了Arch Linux的包管理系统pacman。

  2. Cygwin:是提供了完整的类Unix环境,是让windows开发者在开发软件的时候,感觉是在Unix环境下。用它开发出来的程序既可以运行在windows也可以用在unix,但需要重新编译。在windows上运行的时候依赖cygwin1.dll库,它提供了在windows上posix接口。

安装MinGW环境

  1. 先安装MSys2,下载地址为http://sourceforge.net/projects/msys2,安装的时候路径不要有空格。

  2. 安装过程很简单,根据提示安装即可

  3. 安装完后,需要用包管理工具更新系统,首先了解下pacman的命令

常用命令:如下。更多命令)

1
2
3
4
5
6
7
8
9
10
11
12
pacman -S package_name  #安装软件包
pacman -R package_name #删除软件包
pacman -Rs package_name #顺便删除软件包相关依赖
pacman -Syu #升级系统中的所有包
pacman -Ss package #查询软件包
pacman -Qs package #查询已安装的包
pacman -Qi package #显示查找的包的信息
pacman -Ql package #显示你要找的包的文件都安装的位置
pacman -Sw package #下载但不安装包
pacman -U /path/package.pkg.tar.gz #安装本地包
pacman -Scc #清理包缓存,下载的包会在/var/cache 这个目录
pacman -Sf pacman #重新安装包

更新过程:运行msys2_shell.bat,启动MSys2命令行窗口

1
2
3
4
5
6
# 升级系统中的所有包
pacman -Syu
# 更新核心包,更新完后执行autorebase.bat
pacman -S --needed filesystem msys2-runtime bash libreadline libiconv libarchive libgpgme libcurl pacman ncurses libintl
# 再次启动msys2_shell.bat,用以下命令确认是否为最新
pacman -Syu

如果更新太慢,把软件源换到国内,修改/etc/pacman.d/中有三个mirrorlist文件,分别为mingw32,mingw64以及msys的源,具体配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
##
## MSYS2 repository mirrorlist
##
## Primary
## msys2.org
## 中国科学技术大学开源软件镜像
Server = http://mirrors.ustc.edu.cn/msys2/REPOS/MSYS2/$arch
Server = http://repo.msys2.org/msys/$arch
Server = http://downloads.sourceforge.net/project/msys2/REPOS/MSYS2/$arch
Server = http://www2.futureware.at/~nickoe/msys2-mirror/msys/$arch/

##
## 32-bit Mingw-w64 repository mirrorlist
##
## Primary
## msys2.org
## 中国科学技术大学开源软件镜像
Server = http://mirrors.ustc.edu.cn/msys2/REPOS/MINGW/i686
Server = http://repo.msys2.org/mingw/i686
Server = http://downloads.sourceforge.net/project/msys2/REPOS/MINGW/i686
Server = http://www2.futureware.at/~nickoe/msys2-mirror/i686/

##
## 64-bit Mingw-w64 repository mirrorlist
##
## Primary
## msys2.org
## 中国科学技术大学开源软件镜像
Server = http://mirrors.ustc.edu.cn/msys2/REPOS/MINGW/x86_64
Server = http://repo.msys2.org/mingw/x86_64
Server = http://downloads.sourceforge.net/project/msys2/REPOS/MINGW/x86_64
Server = http://www2.futureware.at/~nickoe/msys2-mirror/x86_64/
  1. 查看软件包:

MSys2包含了哪些软件包:https://github.com/Alexpux/MSYS2-packages

MinGW-64包含了哪些软件包:https://github.com/Alexpux/MINGW-packages

  1. 安装一些必要的软件包,看个人需要。另外因为我用的是64位系统,且编译的程序也是64位的,所以尽量安装mingw-w64的包。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
pacman -S autoconf
pacman -S autogen
pacman -S automake
pacman -S vim
pacman -S tar
pacman -S zip
pacman -S unzip
pacman -S mingw-w64-x86_64-pkg-config
pacman -S mingw-w64-x86_64-gcc
pacman -S mingw64/mingw-w64-x86_64-cmake
# 在mingw64/bin目录下,执行cp mingw32-make.exe make.exe
pacman -S mingw64/mingw-w64-x86_64-make
pacman -S mingw-w64-x86_64-luajit
pacman -S mingw-w64-x86_64-doxygen
pacman -S mingw-w64-x86_64-graphviz
# qt包有1g多,看需要安装,这里安装主要是让cmake支持cmake-gui
pacman -S mingw-w64-x86_64-qt5

使用MinGW环境

  1. 尽量使用MinGW工具,而不安装windows工具。如

    • cmake
    • make
    • lua/luajit
    • doxygen
    • graphviz
  2. Git是例外,因为在git目录下,使用自己安装的MinGW显示Git状态速度特别慢,而用Git自带的MinGW则非常快。测试函数如下

1
2
3
4
# 这两个是跟显示Git状态相关的脚步,具体内容google
# curl https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash -o ~/.git-completion.bash
# curl https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh -o ~/.git-prompt.sh
time __git_ps1
  1. 所以一般情况下,不用自己安装的MinGW,而是使用Git自带的MinGW。这样一来,又解决另外一个问题
    • 命令行工具问题,原因是
      • windows的cmd不是很好用
      • 像cmder的工具总是有这样那样的bug
      • 工具链够全,且容易扩展,在windows的PATH中添加“C:\msys64\mingw64\bin”目录
  1. 需要包管理的时候,还是使用msys2_shell.bat,但建议使用快捷方式,加以下参数
1
2
3
4
5
-use-full-path  # 使用windows的PATH全路径
-mingw64 # 使用mingw64
#mingw32 : 优先使用 msys64/mingw32 下的工具;
#mingw64 : 优先使用 msys64/mingw64 下的工具;
#msys2 : 两个都不使用,只用自身 msys 的工具;
  1. 改进Git自带的MinGW,看着更加舒适些。它是使用mintty作为终端模拟的,在“~目录”下加“.minttyrc”文件,内容如下
1
2
3
4
5
6
7
8
9
10
BoldAsFont=-1
CursorColour=0,255,64
CursorType=block
Font=Consolas
FontHeight=12
Locale=zh_CN
Charset=UTF-8
Columns=120
Rows=30
Term=xterm-256color

比特币全节点部署

发表于 2018-07-29 |

选型

比特币节点有很多实现

  • bitcoin core:官方节点,c/c++实现,正式网络大多数都是用这个来运行全节点
  • btcd:golang的实现版本,如果用golang来写一些功能,可以参考这个代码
  • libbitcoin:c/c++实现,特点是它有较好的工具链
  • parity-bitcoin:rust实现,是以太坊创始人之一Gavin Wood的新公司Parity Technologies下的一个产品,它同样也实现了以太坊rust版本

还有很多其他实现,如java版本和js版本。如果用作商业用途,那bitcoin core必然是最稳妥的选择。所以这里选择了bitcoin core。

服务器配置

  • 硬盘:500G。比特币从08年开始运行,已经积累了大量数据,区块链内容大小达210G。
  • 内存:16G。一般来说4G就够,但如果要查历史记录,需要加载完整的交易索引表-tindex,这导致需要8G+的内存
  • cpu:4核。
  • 带宽:一般就行。阿里云的一般2-3天就能同步完。
  • 系统选择:centos 7版本

节点设置

  • 下载bitcoin coreLinux版本bitcoin-0.16.1-x86_64-linux-gnu.tar.gz
  • 解压到系统目录
1
tar -xzvf bitcoin-0.16.1-x86_64-linux-gnu.tar.gz -C /usr/local
  • bitcoin的默认配置目录为 ~/.bitcoin/bitcoin.conf,填写以下配置,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# This config should be placed in following path:
# ~/.bitcoin/bitcoin.conf

# [core]
# Specify a non-default location to store blockchain and other data.
datadir=/data/btc_data
# Set database cache size in megabytes; machines sync faster with a larger cache. Recommend setting as high as possible based upon machine's available RAM.
dbcache=10240
# Maintain a full transaction index, used by the getrawtransaction rpc call.
txindex=1

# [rpc]
# Enable Add Witness Address RPC

deprecatedrpc=addwitnessaddress

# Accept command line and JSON-RPC commands.
server=1
# Accept public REST requests.
rest=1
# Bind to given address to listen for JSON-RPC connections. This option is ignored unless -rpcallowip is also passed. Port is optional and overrides -rpcport. Use [host]:port notation for IPv6. This option can be specified multiple times. (default: 127.0.0.1 and ::1 i.e., localhost, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)
rpcbind=127.0.0.1:8332

rpcuser=btcuser
rpcpassword=btcpassword

# rpcallowip=0.0.0.0
  • 启动bitcoin
1
bitcoind -daemon
  • 关闭bitcoin,一定要用以下命令,否则会有可能导致数据异常,需要重新同步数据
1
bitcoin-cli stop
  • 一些其他命令
1
2
3
4
5
6
7
8
# 查看网络状态:
bitcoin-cli getnetworkinfo
# 查看网络节点:
bitcoin-cli getpeerinfo
# 查看区块链信息:如同步进度、
bitcoin-cli getblockchaininfo
# 查看所有命令
bitcoin-cli help
  • 其他,确保ntp服务是开启的,大多数区块链都要求开启。

其他工具

  • 比特币全球节点分布
  • 比特币浏览器
  • 比特币在线RPC接口
  • 比特币RPC接口解析
  • 比特币交易费查询
  • 比特币配置工具
  • 推荐书:精通比特币

微博爬虫技术方案

发表于 2018-07-13 |

技术选型

  • 目的:实现爬取相关微博的评论、转发、点赞等信息
  • 方案:
    • 在网上搜索了一遍后,相对觉得python比较好用。现存的解决方案多,实现爬虫开发速度快,且开源项目也多,但大多数都是娱乐性质的
    • 又找了一遍后,觉得WeiboSpider这个项目相对可以商业化,就基于这个项目来实现吧
    • WeiboSpider使用到的工具:python3.5、mysql、redis

技术架构

  • 原WeiboSpider架构,主要使用技术celery库,分成三个部分

    • 使用定时器触发事件:如每隔20小时登录一次,每隔5分钟执行一次抓取评论、抓发和点赞信息,定时器有以下2中方法
      • crontab,定时调用下python脚本
      • 使用celery功能,如”celery beat -A tasks.workers -l info”
    • 使用celery爬取微博:celery会把触发事件插入到redis,celery开启工作线程执行爬取
      • “celery -A tasks.workers -l info”
    • 工作线程把爬取的内容插入到数据库,目前使用的是mysql
  • 在原来的基础上,加了两个服务

    • 爬虫前端服务:
      • 提供微博的实时接口,如查询等功能,这些功能因为数据量太大,就直接转向微博
      • 定时触发事件功能
    • 接口服务:
      • 多种接入协议支持,如http,ws等
      • 转发微博的实时接口,对接到爬虫前端服务
      • 这层接口更加业务化,它从数据库组织数据,发送给应用端

注意的问题

  • WeiboSpider中需要注意的问题
    • 数据库连接不支持多线程
    • 数据库连接长时间没有操作,会失去连接

Managing OneSelf 整理

发表于 2018-06-30 |

参考文献

英文版本

中文翻译

中文总结

前言

《Managing Oneself》翻译成《自我管理》,是摘自德鲁克1999年出版的《21世纪的管理挑战》一书,这是此书的最后一章内容。

历史上的伟人,不但天资卓越,而且还很会管理自我,所以才取得了不同于常人的成就。

在当今的世界,由于社会的变革,更需要我们能够自我管理,即便你是有点天赋的人。

那么如何管理呢,德鲁克介绍了以下几个方面

  • 我的长处是什么?
  • 我的工作方式是怎样的?
  • 我的价值观是什么?
  • 我属于何处?
  • 我该做什么贡献?
  • 我要如何处理人际关系?
  • 我改如何管理后半生?

我的长处是什么?

不是每个人都很清楚自己的长处是什么,即使知道,可能认识也不够清晰。但要成功,就要做自己擅长的事情。

这里有一种了解长处的方法:回馈分析法(feedback analysis)。每当要做出决定或者采取重要行动时,记录下自己对结果的预期;一段时间后,在将结果与自己的预期进行比较和分析。

当使用回馈分析法(feedback analysis)后,会发现哪些一些事情,如:

  • 专注自己的长处,把自己放到能发挥自己长处的地方去
  • 加强自己的长处,根据回馈分析法,知道了自己的长处,但在这个长处上,还缺乏一些技能和知识,那么去填补它们
  • 根据回馈分析法,会发现对一些事物的傲慢与偏见,去克服它们
  • 根据回馈分析法,会发现一些阻碍自己的坏习惯,如哪些影响工作成效和表现的事情
  • 根据回馈分析法,会发现一些社交中举止言行不得体和缺乏礼貌的地方
  • 同样会发现自己不擅长的事情,那我们应该尽量少把精力浪费在那些不能胜任的领域上,因为“从无能到平庸”要比“从一流到卓越”需要人们付出多得多的努力

我的工作方式是怎样的?

一个人的工作方式也是独一无二的——这是由人的个性所决定的。一个人的工作方式也基本固定,它可以略微有所调整,但是不可能完全改变

我属于读者型,还是听者型?

我如何学习?知行合一

一些人作为团队成员工作最出色;另一些人单独工作最出色。

一些人当教练和导师特别有天赋;另一些人却没能力做导师。

许多人做顾问时的表现会很出色,但是不能够承担决策的负担和压力。与此相反,也有许多人需要顾问来迫使他们思考,随后他们才能做出决定,接着迅速、自信和大胆地执行决定。

我是在压力下表现出色,还是适应一种按部就班、可预测的工作环境?

我是在一个大公司还是在一个小公司中工作表现最佳?

Do not try to change yourself。work to improve the way you perfrom。

我的价值观是什么?

如果一个组织的价值体系不为自己所接受或者与自己的价值观不相容,人们就会备感沮丧,工作效力低下。

组织和人一样,也有价值观。为了在组织中取得成效,个人的价值观必须与这个组织的价值观相容。两者的价值观不一定要相同,但是必须相近到足以共存。

一个人的工作方式和他的长处很少发生冲突,相反,两者能产生互补。但是,一个人的价值观有时会与他的长处发生冲突。一个人做得好甚至可以说是相当好、相当成功的事情——可能与其价值体系不吻合。在这种情况下,这个人所做的工作似乎并不值得贡献毕生的精力(甚至没必要贡献太多的精力)。

我属于何处?

成功的事业不是预先规划的,而是在人们知道了自己的长处、工作方式和价值观后,准备把握机遇时水到渠成的。知道自己属于何处,可使一个勤奋、有能力但原本表现平平的普通人,变成出类拔萃的工作者。

我该做什么贡献?

要回答这个问题,他们必须考虑三个不同的因素:

  • what does the situation need?
  • from strengths、way of work、values, What is the greatest contribution i can make?
  • what results have to be achieved to make a difference?

我要如何处理人际关系?

每个人都会执意展现自己作为人的个性。这就是说,每个人都有自己的长处,自己的做事方式和自己的价值观。因此,要想卓有成效,你就必须知道共事者的长处、工作方式和价值观。

人际关系责任的另一方面是沟通责任。明确别人在做什么、如何做、重要性、期望结果,以及他对别人的期望是什么

组织已不再建立在强权的基础上,而是建立在信任的基础上。人与人之间相互信任,不一定意味着他们彼此喜欢对方,而是意味着彼此了解。因此,人们绝对有必要对自己的人际关系负责。这是一种义务。不管一个人是公司的一名成员,还是公司的顾问、供应商或经销商,他都需要对他的所有共事者负起这种责任。所谓共事者,是指在工作上他所依赖的同事以及依赖他的同事。

我改如何管理后半生?

其实说的更像是个人的规划,那为啥要规则,有几个原因:

  • 抗风险,反脆弱,我们需要有更多的选择
  • 人都会疲倦,对原来的工作缺乏满足感
  • 在现在社会,个人比组织更长寿,甚至比行业更长寿
  • 我们都崇尚成功,都不想向下流动

最简单的方法,是发展第二职业,有几种选择,根据自身的情况去选择:

  • 投身于新的工作
  • 发展一个平行职业
  • 创业

管理好后半生有一个先决条件:你必须早在你进入后半生之前就开始行动

区块链跨链技术

发表于 2018-06-19 |

原因

无法跨链的区块链就如网站没有浏览器,互联网没有搜索引擎。

跨链技术是实现区块链价值互联的关键,它是把区块链从分散的孤岛中拯救出来的良药,是区块链向外拓展和连接的桥梁。

要素

基础的跨链满足以下5个步骤:

  1. 在A链的用户A向在B链的用户B发起兑换请求
  2. 跨链协议锁定A链币
  3. 跨链协议锁定等值数量的B链币
  4. 将B链币发到用户B的钱包地址,同时拿走锁定的用户A的链币
  5. 在A链上用户A的币被转走,同时在B链上用户B得到等值的币

根据这5个步骤,需要区块链5项能力

  1. 便携式资产(portable assets):资产可以多条链之间来回转移和使用
  2. 满足原子性交换(atomic swap):跨链资产兑换是安全的而且同步发生的。(不同链上的两位用户可以发起两笔传输交易,要么在两个账本上一起执行,要么两个账本都不执行,即原子性)
  3. 带有跨链互通性,具备他链信息和事件的读取和验证能力(Cross-chain oracle issues):在某些情况下,一个链(如A链)的智能合约执行机制可能是依赖另一个链(B链)的条件触发,所以A链要能获得B链的所有相关条件状态,即c具备他链信息和事件的读取和验证能力。
  4. 资产留置权(Asset encumbrance):在某些情况下,相关联的两个链资产同时需要被锁定,如抵押品或者法院强制执行的扣押等。
  5. 跨链执行合约(General cross-chain contracts):例如根据链A的股权证明在链B上分发股息等。

跨链技术主要有以下几种

  • 公证人机制(notary schemes)
  • 侧链/中继(sidechains/relays)
  • 哈希锁定(hash-locking)
  • 分布式私钥控制(distributed private key control)
  • 公证人机制+侧链混合技术(notary schemes + sidechains mixing technology)

img

公证技术:如瑞波Interledger协议 ★★★

在2012年,ILP由瑞波实验室提出,解决不同账本之间的协同。流程如下

  1. Alice是拥有A链的账户,Bob是拥有B链的货币,Cot是拥有A、B链的货币;Alice将向Bob进行一笔交易(如转账)
  2. Alice通过其他通讯手段,得到Bob提供的一个“共享密码”以及Bob在ILP网络中的对应唯一地址(如bob.ripple.rHCvhtqhXuBvWt5g79gyXfpG8VcrvUm9E9)
  3. Alice向Cot询价,Cot根据Alice的转账金额和市场行情算出总的交易额(包括交易费)
  4. Alice根据ILP规定生成ILP包,指定目标目标地址为Cot,同时给予ILP包的私有内容和“共享密码”生成一个“条件原像”,对“条件原像”HASH生成交易托管所需要的“条件”
  5. Alice在A链上发起一个托管交易(转账),托管条件为4所生成的条件,设置超时时间
  6. Cot在A链上检查到一笔涉及自己的托管交易,同时收到Alice的ILP包;计算和校对需要交易的额度后,将ILP包目标地址修正为Bob,并在B链上发起一个托管操作,设定交易条件为Alice的交易条件,设定超时时间,超时时间小于5.的时间,然后将ILP包发送给Bob
  7. Bob收到ILP包,用“公共密码”解出“条件原像”,用HASH校对“条件”;同时检测到B链上的托管交易,校对金额后,转入“条件原像”,确认收到交易的金额
  8. Cot在B链检测到涉及自己的托管交易被确定,分析交易数据,得到“条件原像”;把“条件原像”输入到A链上,并确认交易,收到交易的金额和手续费
  9. Alice在A链上检测到涉及自己的托管交易被确定,此次交易完成

img

侧链技术:BTC Relay ★★

BTC Relay 是在以太坊基金会支持下诞生并成长起来的,属于早期的侧链技术。它在以太坊上建立一个bitcoin轻钱包,用于操作bitcoin,并给以太坊智能合约提供操作bitcoin的接口,这样用合约就能完成BTC和ETH的交易。是非常简单的一种跨链技术。但它的交易费用特别高。

img

中继技术:Polkadot ★★★★★ (其他如Cosmos,tendermint团队开发)

Polkadot(Parity公司开发)将区块链共识分成两个部分:有效性和一致性。有效性的概念是比如我有10个比特币,我转给A是有效的,我转给B也可以是有效的。但一致性的概念就是我只能转给其中某一个人,即使我发出了两笔有效的交易,最终网络会共识出一条最长链来达成一致,另一个交易会被丢弃。更加概括性地讲就是有效性负责运算,一致性负责投票,一个是强CPU依赖的,一个是强出块权依赖的。

Polkadot 结构中核心有两个部分:中继链和平行链,中继链负责一致性,平行链负责有效性。中继链采用POS共识算法,将主要借鉴Honeybarger,还有Tendermint。平行链由很多固定身份的收集人管理,以收集交易手续费为激励,为中继链提供自己的块头和跨链交易相关的证明数据,这部分数据在Polkadot里称为平行链的候选块,将来由中继链的验证人随机选定。由于平行链也不一定真有一条链,所以这里的块也是泛指。中继链会分成两类,第一类是类似以太坊和比特币这样有自身共识系统的区块链,他们有自身的POW矿工来维持链的运转,他们不能直接作为平行链参与到Polkadot网络中来,而是需要新成立一些收集人组建转接桥系统,将以太坊区块的数据整理为中继链所需的格式,这个转接桥系统才是Polkadot的平行链。第二类是还没有出现的过的区块链系统,他们将来的出块人就是收集人,他们链区块的决定权是由中继链的验证人决定的,这类系统可能才真正是Polkadot所设想的未来链。

img

哈希锁定技术:Lighting network ★★

闪电网络基本原理:Alice在A链与Bob在B链进行一笔交易

  1. Alice在A链用密码H=HASH(S)锁定一笔资产,并设定时限,时限到来前,如果有人能交出S,这笔资产就转给他,否则这笔资产归还给Alice
  2. Alice将H发给Bob
  3. Bob在B链上用H锁定一笔资产,设定时限,小于1.的时限,时限到来前,如果有人能交出S,这笔资产就转给他,否则这笔资产归还给Bob
  4. Alice在B链上交出S,得到Bob锁定的资产,同时B得到了S
  5. Bob在A链上交出S,得到Alice锁定的资产

img

分布式私钥控制技术:FUSION ★★★ (其他如国内开发的WanChain)

Fusion在原链上设立锁定帐号,作为原链上的公证人,用户向fusion发起lock-in请求,然后将原链上的通证交给锁定账户,fusion上的智能合约验证请求,确认原链上的交易后,在fusion链上创造等值原链通证的标记符号,交给用户,之后用户可以在fusion上交易其他链通证的标记符号,提现时,用户在fusion上发起lock-out请求,验证节点将提现的标记符号锁定,用对应链上的锁定账户向用户发起转账,确认转账后销毁fusion上的标记符号。

采用锁定账户作为公证人,不可避免的是锁定账户的密钥控制问题,fusion中采用的是所谓分布式密钥存储的安全方案,本质上就是秘密共享技术,具体可以参考Shamir的(k,n)门限秘密共享方案,简单的理解就类似多重签名技术,由n个验证节点分别持有一部分密钥,每个节点只能知道自己的密钥,然后锁定账户的任何操作都至少要有k个验证节点的密钥,因此只要且必须要有至少k个验证节点通过,锁定帐号才能将锁定的原链资产提现给用户。相较于中心化的交易所,n个验证节点事实上构成了一个多中心的结构,避免了单个中心被攻击的危害,同时不需要设计完全去中心化结构的技术难点。

img

混合技术:Ether Universe ★★★★

以太宇宙分为主链和不同区块链上的子链,主链是整个生态体系中的最重要部分,其承载了整个平台交互逻辑,记录了所有交互信息,链上产生的代币用于支付每次跨链服务所消耗的 gas。子链则用于辅助主链来对其他区块链进行双向锚定。

img

最近遇到的关于docker的问题

发表于 2018-06-15 |

问题1:docker -v 与 onedrive 冲突

  • 问题现象

在windows下docker用Ubuntu镜像生成容器,用-v映射到本地目录,如果这个目录也是onedrive包含的目录,那有可能导致onedrive一直卡在“正在更新文件”中

  • 解决办法

    • 停掉和删除容器
    • 重设onedrive,键盘win+r,输入“%localappdata%\Microsoft\OneDrive\onedrive.exe /reset”
    • 重启操作系统
  • 这种方法但失去了在容器上操作文件后能直接同步到onedrive的功能,暂时用以下办法代替

    • 目录copy一份到别的路径下,然后写一个脚本,按差异复制到onedrive目录

以下是同步脚本

1
2
3
4
5
6
7
set NOWDIR=%~dp0
cd %NOWDIR%

set SRC=...
set DST=...

xcopy "%SRC%\server" "%DST%\server" /s /h /d /y /exclude:uncopy.txt

以下是uncopy.txt文件

1
2
3
4
5
6
7
8
9
10
11
12
*.so
*.o
*.a
*.log
*.dSYM

.idea
*.iml
*.rock
*.rockspec
.DS_Store
*.pid
  • 用系统的任务计划来执行脚本,把文件同步到onedrive下

问题2:docker -v映射目录后,容器中不生效

  • 引起这个问题的原因是更新了操作系统的密码,解决办法如下

    • 打开docker设置,在sharedrives栏,reset credentials…,然后选择shared的盘符,重新输入系统密码
    • 重新生成容器

typescript_learning

发表于 2018-06-06 |

TypeScript,转自legacy的gitbook

安装编译

1
2
npm install -g typescript
tsc hello.ts

tsc 对类型做静态检查,如果有错误,编译会报错,但会继续生成编译结果

基础

  1. 原始数据类型
  • 布尔值
1
let isDone: boolean = false;
  • null类型 和 undefined类型,他俩是所有类型的子类型,即可以赋值给其他类型
1
2
let u: undefined = undefined;
let n: null = null;
  • 数值
1
2
3
4
5
6
7
8
9
let decLiteral: number = 6;
// 16 进制
let hexLiteral: number = 0xf00d;
// ES6 中的二进制表示法
let binaryLiteral: number = 0b1010;
// ES6 中的八进制表示法
let octalLiteral: number = 0o744;
let notANumber: number = NaN;
let infinityNumber: number = Infinity;
  • 字符串
1
2
3
4
5
6
let myName: string = 'Tom';
let myAge: number = 25;

// 模板字符串
let sentence: string = `Hello, my name is ${myName}.
I'll be ${myAge + 1} years old next month.`;
  • 空值, 用于函数返回值
1
2
3
function alertName(): void {
alert('My name is Tom');
}
  • 任意类型
1
2
let myFavoriteNumber: string = 'seven';
myFavoriteNumber = 7;
  • 联合类型
1
2
3
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
  1. 对象的类型
  • 接口
1
2
3
4
5
6
7
8
9
interface Person {
name: string;
age: number;
}

let tom: Person = {
name: 'Tom',
age: 25
};
  • 可选属性,带?
1
2
3
4
5
6
7
8
interface Person {
name: string;
age?: number;
}

let tom: Person = {
name: 'Tom'
};
  • 任意属性
1
2
3
4
5
6
7
8
9
10
interface Person {
name: string;
age?: number;
[propName: string]: any;
}

let tom: Person = {
name: 'Tom',
gender: 'male'
};

使用 [propName: string] 定义了任意属性取 string 类型的值。

需要注意的是,一旦定义了任意属性,那么确定属性和可选属性都必须是它的子属性

  • 只读属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
interface Person {
readonly id: number;
name: string;
age?: number;
[propName: string]: any;
}

let tom: Person = {
id: 89757,
name: 'Tom',
gender: 'male'
};

tom.id = 9527;

// index.ts(14,5): error TS2540: Cannot assign to 'id' because it is a constant or a read-only property.

上例中,使用 readonly 定义的属性 id 初始化后,又被赋值了,所以报错了。

注意,只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候

  1. 数组类型
  • 基本数组
1
let fibonacci: number[] = [1, 1, 2, 3, 5];
  • 泛型数组
1
let fibonacci: Array<number> = [1, 1, 2, 3, 5];
  1. 函数类型
1
2
3
4
5
6
7
8
9
// 函数声明(Function Declaration)
function sum(x, y) {
return x + y;
}

// 函数表达式(Function Expression)
let mySum = function (x, y) {
return x + y;
};
  1. 类型断言
1
2
3
4
5
6
7
function getLength(something: string | number): number {
if ((<string>something).length) {
return (<string>something).length;
} else {
return something.toString().length;
}
}
  1. 声明文件
1
2
3
4
// jQuery.d.ts
declare var jQuery: (string) => any;

jQuery('#foo');
  1. 内置对象
  • ECMAScript内置对象,在typescript核心库中已经定义好了,还扩展了内置对象,如DOM、BOM等

  • 其他第三方,如node,可以用npm来生成

1
npm install @types/node --save-dev

进阶

  1. 类型别名,关键词type
1
2
3
4
5
6
7
8
9
10
11
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
if (typeof n === 'string') {
return n;
}
else {
return n();
}
}
  1. 字符串字面量类型,关键词type
1
2
3
4
5
6
7
type EventNames = 'click' | 'scroll' | 'mousemove';
function handleEvent(ele: Element, event: EventNames) {
// do something
}

handleEvent(document.getElementById('hello'), 'scroll'); // 没问题
handleEvent(document.getElementById('world'), 'dbclick'); // 报错,event 不能为 'dbclick'
  1. 元组,数组合并了相同类型的对象,而元组(Tuple)合并了不同类型的对象。
1
2
3
4
5
6
let xcatliu: [string, number];
xcatliu[0] = 'Xcat Liu';
xcatliu[1] = 25;

xcatliu[0].slice(1);
xcatliu[1].toFixed(2);

越界的元素,当赋值给越界的元素时,它类型会被限制为元组中每个类型的联合类型:

1
2
3
4
let xcatliu: [string, number];
xcatliu = ['Xcat Liu', 25];
xcatliu.push('http://xcatliu.com/');
xcatliu.push(true); // 报错,不能push boolean类型
  1. 枚举,关键词enum
  • 普通枚举

枚举成员会被赋值为从 0 开始递增的数字,同时也会对枚举值到枚举名进行反向映射:

1
2
3
4
5
6
7
8
9
10
11
enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat};

console.log(Days["Sun"] === 0); // true
console.log(Days["Mon"] === 1); // true
console.log(Days["Tue"] === 2); // true
console.log(Days["Sat"] === 6); // true

console.log(Days[0] === "Sun"); // true
console.log(Days[1] === "Mon"); // true
console.log(Days[2] === "Tue"); // true
console.log(Days[6] === "Sat"); // true
  • 常数枚举
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const enum Directions {
Up,
Down,
Left,
Right
}

let directions = [Directions.Up, Directions.Down, Directions.Left, Directions.Right];
```

常数枚举与普通枚举的区别是,它会在编译阶段被删除,并且不能包含计算成员。

- 外部枚举

5. 类

- 属性与方法

使用 class 定义类,使用 constructor 定义构造函数。

通过 new 生成新实例的时候,会自动调用构造函数。

``` typescript
class Animal {
constructor(name) {
this.name = name;
}
sayHi() {
return `My name is ${this.name}`;
}
}

let a = new Animal('Jack');
console.log(a.sayHi()); // My name is Jack
  • 继承

使用 extends 关键字实现继承,子类中使用 super 关键字来调用父类的构造函数和方法。

1
2
3
4
5
6
7
8
9
10
11
12
class Cat extends Animal {
constructor(name) {
super(name); // 调用父类的 constructor(name)
console.log(this.name);
}
sayHi() {
return 'Meow, ' + super.sayHi(); // 调用父类的 sayHi()
}
}

let c = new Cat('Tom'); // Tom
console.log(c.sayHi()); // Meow, My name is Tom
  • 存取器

使用 getter 和 setter 可以改变属性的赋值和读取行为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Animal {
constructor(name) {
this.name = name;
}
get name() {
return 'Jack';
}
set name(value) {
console.log('setter: ' + value);
}
}

let a = new Animal('Kitty'); // setter: Kitty
a.name = 'Tom'; // setter: Tom
console.log(a.name); // Jack
  • 静态方法

使用 static 修饰符修饰的方法称为静态方法,它们不需要实例化,而是直接通过类来调用:

1
2
3
4
5
6
7
8
9
class Animal {
static isAnimal(a) {
return a instanceof Animal;
}
}

let a = new Animal('Jack');
Animal.isAnimal(a); // true
a.isAnimal(a); // TypeError: a.isAnimal is not a function
  • public private 和 protected

  • 抽象类

abstract 用于定义抽象类和其中的抽象方法。

抽象类是不允许被实例化的;抽象类中的抽象方法必须被子类实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
abstract class Animal {
public name;
public constructor(name) {
this.name = name;
}
public abstract sayHi();
}

class Cat extends Animal {
public sayHi() {
console.log(`Meow, My name is ${this.name}`);
}
}

let cat = new Cat('Tom');
  1. 类与接口
  • 类继承接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
interface Alarm {
alert();
}

class Door {
}

class SecurityDoor extends Door implements Alarm {
alert() {
console.log('SecurityDoor alert');
}
}

class Car implements Alarm {
alert() {
console.log('Car alert');
}
}
  • 类继承多个接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
interface Alarm {
alert();
}

interface Light {
lightOn();
lightOff();
}

class Car implements Alarm, Light {
alert() {
console.log('Car alert');
}
lightOn() {
console.log('Car light on');
}
lightOff() {
console.log('Car light off');
}
}
  • 接口继承接口
1
2
3
4
5
6
7
8
interface Alarm {
alert();
}

interface LightableAlarm extends Alarm {
lightOn();
lightOff();
}
  • 接口继承类
1
2
3
4
5
6
7
8
9
10
class Point {
x: number;
y: number;
}

interface Point3d extends Point {
z: number;
}

let point3d: Point3d = {x: 1, y: 2, z: 3};
  • 混合类型
1
2
3
4
5
6
7
8
interface SearchFunc {
(source: string, subString: string): boolean;
}

let mySearch: SearchFunc;
mySearch = function(source: string, subString: string) {
return source.search(subString) !== -1;
}
  • namespace,之前叫module,内部使用export导出,引入的时候用全名或者import成别名
1234

Lucus Gu

32 日志
2 标签
RSS
© 2017 — 2019 Lucus Gu
由 Hexo 强力驱动
|
主题 — NexT.Mist v5.1.4