学如逆水行舟,不进则退 / Sailing against the current

Study is like sailing against the current; either you keep forging ahead or you keep falling behind.

sailing-boat-1593613_960_720.jpg

几年前工作的时候,有一段时间被公司强迫做的几天Python程序员,在这之前我做的工作主要使用C++和Fortran语言。

但是第一次接触Python我就被它的强大和便捷所吸引,为了做好公司交代的任务,我还特意从京东网购了原价148元的《Python编程(影印版)》上下册,还特意买了一本《普通化学原理与应用第八版(影印版)/General Chemistry Principles and Modern Applications Eighth Edition》。

之后我发现那本化学书我根本啃不动,只好束之高阁了。好在在Python书和专业搞化学的同事的帮助下,我顺利的完成了任务。那之后,虽然我依旧坚信PHP是世界上最好的语言😀,但对Python也比较偏爱了。之后用Python写过一些脚本,比如分析Apache的日志文件找出bad boy,工作的还算完美。可惜后来忙于工作和其它事情,就很少接触Python了,一下子荒废好多年。

来玩Steemit之后,因为种种原因,重新拾起Python, 再次为它的强大和便捷所吸引。但是却发现,好多Python的知识已经忘得一干二净了。我边学边用,很多时候代码写着写着,然后惊觉这部分我以前用过呢,记忆从模糊到清晰,以前写过的代码,当时的所学所思一点点的仿若突然忆起的梦境,不禁喟叹,这走了多少冤枉路啊。

art-1238602_960_720.jpg
《增广贤文》中有一句话:学如逆水行舟,不进则退

这句话打小起,便被父母和老师告知了无数次,但是我们何曾记在心上呢?

只有当我们的小舟倒退到千里之外,才惊觉啊,如果当初我们再努力一点点,何至于现在落后这么多!

其实不光Python,我掌握的很多技能,要么过时了,要么忘记了

比如那时候字处理用wps, 表格用cced,后来学到的先进的数据库是foxbase,我还用汇编语言写过键盘监控程序,用VB做过一些小项目,用lisp语言autocad的插件并应用到激光切割控制系统中去等等等等,然而现在这些除了当作历史回忆一下还有什么用呢?

至于PHP, C++什么的,我觉得我之前掌握的东西已经完全跟不上潮流了,何况我之前掌握的东西已经快被我忘干净了。

至于新的语言和工具,更是没有年轻时看到新东西时激动和猎奇的心情了。

rubber-duck-1401225_960_720.jpg

常常用来安慰自己的话,就是“吾生也有涯,而知也无涯。以有涯随无涯,殆已!”于是心安理得的看着表泡泡澡,舒服一秒是一秒,毕竟人生得意须尽欢嘛,唯一遗憾的是,还没得意起来😭

以有涯随无涯是否会殆已,我不清楚,但是这样老知识忘干净,新知识不接触,以后可真的要殆已了。

撰文一篇,自勉一下吧。

(封面图源 :pixabay)


This page is synchronized from the post: 学如逆水行舟,不进则退 / Sailing against the current

Python字符串引号的小问题 / 多个朋友多条路

在之前的系列帖子中:

我通过例子介绍了一些API的用法。

hands-2706109_960_720.jpg

API示例

简单挑选几个列举如下:

获取市场报价

curl -s --data '{"jsonrpc": "2.0", "method": "call", "params": ["market_history_api", "get_ticker", []], "id": 1}' https://steemd.steemit.com

又比如:

获取指定用户当前挂单信息

curl -s --data '{"jsonrpc": "2.0", "method": "call", "params": ["database_api", "get_open_orders", ["deanliu"]], "id": 1}' https://steemd.steemit.com

其实还有很多有用的API,比如说:

获取账户信息的

curl -s --data '{"jsonrpc": "2.0", "method": "call", "params": ["database_api", "get_accounts", [["oflyhigh"]]], "id": 1}' https://steemd.steemit.com

API "params" 组成

更多的API介绍,不是我们这篇文章的主题,我想说的是我调试程序过程中遇到的一个事情。

如上述API示例中所描述的那样,去掉固定部分,其实"params"部分是固定的用逗号分隔的三部分组成,比如上述例子中的"params"部分:

"market_history_api", "get_ticker", []
"database_api", "get_open_orders", ["deanliu"]
"database_api", "get_accounts", [["oflyhigh"]]

遇到的问题

问题就出在第三部分上。

我想把第三部分 [“deanliu”]用变量的方式传递给固定的字符串模板,然后组合出上述API调用。

其中核心代码如下:

1
2
3
list = ["deanliu"]
str = str(list)
print(str)

看到这个结果我就哭了😭

  • 我想得到是这样的字符串:'["deanliu"]'
  • 结果得到是这样的字符串:"['deanliu']"

这就有些尴尬了,因为第二字符串传递到模板里会导致错误的结果。

寻求帮助

作为一个初学者,我研究了半天,也没有找到合适的方式来解决这个问题,我甚至准备写一段代码来对得到的字符串进行转换,但是能否实现先不说,我总觉得这样的处理方式不优雅。

恰巧看我的一个QQ群里有几个夜猫子闲聊,其中一个QQ好友据我所知玩过很长时间的Python,我把上述例子发给他,并向他求教,如何把"['deanliu']"转换成'["deanliu"]',他马上给我回复说试试json.dumps

于是我改写了上述例子变成了这样:

1
2
3
4
import json
list = ["deanliu"]
str = json.dumps(list)
print(str)


完美地解决了我的问题。

结论

这个问题,对于高手(比如我这个朋友)而言,就是一句话解决。

而如若没有他的指点,我可能耗费数个小时的时间来寻找解决方法,并且极有可能用极其不优雅的方式实现。

多个朋友多条路, 古之人诚不欺我!

(封面图源 :pixabay)


This page is synchronized from the post: Python字符串引号的小问题 / 多个朋友多条路

再次提醒大家防范钓鱼信息,就在昨晚CN区一个声望分67级的账户被盗!!! / Avoid phishing

大概六小时之前,也就是北京时间凌晨一点时候,我随意浏览cn标签下的新帖子, 并看到这样一篇帖子:

第一反应,有人冒充 @twinkledrop,我要进去看看是不是骗子,如果是,我要把她踩死,以免她继续骗人。

进去一看,再对比一下https://steemd.com上的数据,发这个帖子的不是骗子,而是***@twinkledrop 的账户被钓鱼,资金被转走,密码被修改!*


事情始末

让我们一起回顾一下事情始末。

  • 一: 14小时之前(2017-10-21 09:50:48 UTC), @twinkledrop 发了如下帖子:

  • 二:五分钟之后(2017-10-21 09:55:54 UTC) , @cheetoh 回复了这个帖子

    (原回复已经被删除,我复制个类似的)

  • 三: 五分钟之后(2017-10-21 10:01:18 UTC) , @twinkledrop 的密码被修改

  • 四:四分钟之后(2017-10-21 10:05:24 UTC) , 骗子收取了一下这个账户下未声明的收益

  • 五:三分钟之后(2017-10-21 10:08:21 UTC) , 骗子成功将账户内的活期余额转走

从上边数据分析可知,从骗子撒网钓鱼,到骗子成功把钱转走,一共才用了13分钟(09:55:54 - 10:08:21)!


盗号流程

那么 @twinkledrop 是如何上当的?上述步骤2和步骤3之间发生了什么?让我们尝试重现一下:

  • 我们注意到骗子的头像和名称以及回复风格都和 @cheetah 非常相似

  • 骗子的链接显示是steemit.com 上的内容,看起来可信度更高

  • 点击链接后,打开一个其它站点,并弹出一个和STEEMIT登陆对话框相似度极高的登陆框,提示用户登录
    (昨晚看到的没截图,骗子网站暂时关闭了)

  • 用户一不小心输入账户密码,则密码被骗子获取

为什么明明是steemit.com/xxxx 链接,会打开第三方盗号站点呢?
我们来看一下骗子回复的原始内容

明白了吧,就是显示的内容和链接根本是两码事!


盗号之后骗子干什么?

你认为账户被盗,骗子修改密码并把钱转走就完事了?太幼稚!

让我们来看看 @twinkledrop 这个账户被盗之后还干什么了?

什么,去和别人聊天去了?让我们看看都聊些什么?

卖糕的,用被盗的账户去继续钓鱼,这骗子,太缺德了! 然后,@twinkledrop 被好多大号踩 😭


如何防范

在 @twinkledrop 发帖以及被盗号事情发生三小时之前,我发过一个帖子提醒大家注意密码安全

其中,我提到:

  • 导出Posting Key 以及Active Key,平时使用这个两个私钥发帖和转账。
  • 将主密码离线保存到移动介质上,并保存两份以上COPY,放置到安全的地方。
  • 无论在什么网站和程序上,都不要提供主密码,除非你需要修改密码。

如果 @twinkledrop 能看到我的帖子,并按第一条操作,那么骗子就只能得到Posting 私钥了,多说用来发发贴。

在17天前,我还发过一个提示大家注意防范钓鱼信息的帖子

在其中,我提到:

  • 不要相信天上掉馅饼(或者铁饼)的事情
  • 仔细核对信息内容,尤其是信息中的链接
  • 提高警惕,不要有过多的好奇心
  • 一旦有一些事情发生,并且自己叫不准是否有问题的时候,可以向专业人士请教

如果, @twinkledrop 能按我两个帖子中的提示去做,那么被盗号的悲剧就不会发生了,一声叹息!


结束语

随着STEEM流行度越来越高,并且账户里都是真金白银,骗子们也会发现并盯上这块肥肉的,以后类似的钓鱼、诈骗将会越来越多,所以我们要提高警惕,账户被盗,我们所有辛勤努力的收获都将付之东流,为他人做了嫁衣裳。

但愿 @twinkledrop 能成功恢复账户,拿回这个账户里的SP。

用昨天的帖子的标题做结尾:
宜未雨而绸缪,毋临渴而掘井!

(封面图源 :pixabay)


This page is synchronized from the post: 再次提醒大家防范钓鱼信息,就在昨晚CN区一个声望分67级的账户被盗!!! / Avoid phishing

关于密码安全,别心存侥幸 (宜未雨而绸缪,毋临渴而掘井)!

昨天一个STEEMIT的朋友找到我,他在STEEMIT的一个账户密码找不到了,期望我能帮他找回。这个账户是他委托我代为注册的一个公益账户,里边有大致近300 SBD,说多不多,说少也不少。一旦这个账户无法找到,他就得自掏腰包去补足这部分金额了。

这个朋友是STEEMIT老鸟,注册的比我还早,也一直活跃,按说不该犯这种低级错误。或许是因为这个公益账户不需要经常登陆,所以他把密码藏到了一个足够安全的地方,安全到当他自己想找的时候,也找不到了。😭

privacy-policy-2117996_960_720.jpg
(图源:pixabay)

如果你进入过STEEMIT的密码修改页面,你会看到如下提示:

  • The first rule of Steemit is: Do not lose your password.
  • The second rule of Steemit is: Do not lose your password.
  • The third rule of Steemit is: We cannot recover your password.
  • The fourth rule: If you can remember the password, it’s not secure.
  • The fifth rule: Use only randomly-generated passwords.
  • The sixth rule: Do not tell anyone your password.
  • The seventh rule: Always back up your password.

其中第三条原则就是密码不能恢复。

尝试恢复

但是STEEMIT还有一个Recover Account,这又是什么鬼?

为了让我这个朋友死心安心,我特意进了一下这个恢复账户的页面

输入他的账户,提示信息如下:
We are unable to recover this account, it has not changed ownership recently.

也就是说最近30天内没改过密码的没法恢复。

这个Stolen Accounts Recovery,其实是应用于这样的场景,你的密码被盗,小偷修改了你的密码,然后在骗子修改的30天内,你发觉了这个事情,然后来这个页面用之前的密码进行恢复。注意:你必须有小偷修改密码之前的密码,否则是无法恢复的。

所以,像我这个朋友这样,既没被盗也没改过密码的,又找不到之前密码的,就没指望了。

找回密码

知道密码没法回复这个不幸的消息后,我马上兴奋地沮丧地与他分享。

假惺惺地安慰他:其实密码并没有丢,只不过它在这个世界的某个角落里,你还没有找到而已。既然电脑没被盗,没重装,没格式化,没遭遇水灾火灾地震战争之类的灾害,慢慢找,总会找到的。

不曾想,我这个朋友是个实惠人,对着电脑奋战了一天一宿,然后告诉我密码找到了,这真是让人甚为遗憾非常开心。

虽然密码找回了,但是这种找回方式和STEEMIT的机制没有一丁点关系,所以,切记: We cannot recover your password.

不要心存侥幸,并不是每个人都会向他这样好运气,丢了之后,还能找回来。如果电脑被盗呢?不小心重装呢?不小心硬盘坏掉呢?……

如何保存

password-2781614_960_720.jpg
(图源:pixabay)

通过我朋友这个事例,我觉得有必要再强调一下密码安全的重要性。

毕竟,他这种老鸟都能犯这样的错误,新手们更是很难避免。密码丢了是小事,但是账户里的钱从此就变成冻结的资金了, 这事想想就很令人纠结,不是吗?

那些电脑被盗呢?不小心重装呢?不小心硬盘坏掉的事情,可能一辈子都遇不到,可是——万一遇到呢?

有句话咋说来着: 宜未雨而绸缪,毋临渴而掘井!

那么该如何保存密码呢?我建议如下:

  • 导出Posting Key 以及Active Key,平时使用这个两个私钥发帖和转账。
  • 将主密码离线保存到移动介质上,并保存两份以上COPY,放置到安全的地方。
  • 无论在什么网站和程序上,都不要提供主密码,除非你需要修改密码。

对比一下这三点,我发现我做的其实也不到位,不多写了,保存密码去了。

之前相关文章:


This page is synchronized from the post: 关于密码安全,别心存侥幸 (宜未雨而绸缪,毋临渴而掘井)!

一起来玩内部市场吧(三)!/ Program trading

之前写了两篇文章:

文章一讲述了傻傻的机器人在内部市场赔钱赚钱的故事;文章二,通过实例(by example)介绍了Market history APIs。


(图源:pixabay)

但是问题来了,通过Market history APIs能获得市场行情、交易量、甚至K线图之类的,但是光光获得这些信息,如何变换成财富呢? 一种方法是我们通过分析行情数据,瞅准时机,然后手工挂单,高买低卖低买高卖,攫取财富。然而,人不是机器,没法一直盯盘,市场瞬息万变,手工操作往往让我们错失良机 。所以程序盯盘,程序交易才是王道啊。

当然了,你若和我一样写了个傻傻的程序,那么可能就不单单是赔钱的事啊,还可能被它气到!

好了,是写个赚钱的程序,还是写个气人的赔钱程序,其实用的借口都一样的。这篇文章我们来介绍一下可能用到的东西。

除了上篇文章我们介绍的API外(Market history APIs),在Database API中还有俩接口可能被用到。


get_order_book()

API: order_book get_order_book( uint32_t limit = 1000 )const;
说明: 获取内部市场当前订单信息
Gets the current order book for STEEM:SBD market

调用示例 /Example:
curl -s --data '{"jsonrpc": "2.0", "method": "call", "params": ["database_api", "get_order_book", [5]], "id": 1}' https://steemd.steemit.com

返回信息 / Return:

备注:前文中,我们也介绍了get_order_book(),我对比了两者区别,Database API中的这个返回的信息更详细。


get_open_orders()

API: vector<extended_limit_order> get_open_orders( string owner )const;
说明: 获取指定用户当前挂单信息
Gets the current open orders for specific user.

调用示例 /Example:
curl -s --data '{"jsonrpc": "2.0", "method": "call", "params": ["database_api", "get_open_orders", ["deanliu"]], "id": 1}' https://steemd.steemit.com

返回信息 / Return:

备注: 因为要弄个截图做例子,而我ID @oflyhigh 目前在内部市场没交易,而机器人用的ID open orders太多,所以只好拿 @deanliu 刘美女的ID来做例子啦。


好了,上篇文章加上这半篇,已经把获取市场信息的API都讲完了,接下来,我们看看如何交易:

内部市场交易类型显示的问题这篇文章中,我们曾经分析过钱包实现挂单的代码:

(注:代码太长复制不全,感兴趣的自己来这里看)

在这里还可以看取消订单的代码

不难发现,其实操作就是填充个结构体然后并广播出去。但是和之前描述的各种读取信息API不一样,将结构体广播到网络并使其生效是一个很复杂的事情,其中最关键的部分是用自己的私钥为事务签名,我们这篇文章不讲太多细节(其实是我也不懂)

幸运的是,steem官方的Python库可以帮我们做这些事情,懒人福音啊。

steem官方Python库的交易接口提供了好多功能。


https://github.com/steemit/steem-python/blob/master/steem/dex.py)

比如说:

  • 买入STEEM, 付出SBD
  • 卖出STEEM, 换取SBD
  • 买入SBD, 付出STEEM
  • 卖出SBD, 换取STEEM

但是如我在这篇文章中所描述,根本没必要整这么多嘛,完全可以缩减成两项:

  • 买入STEEM, 付出SBD
  • 卖出STEEM, 换取SBD

好了,写了这么多,想必你对如何玩转内部市场已经有了初步的想法。

接下来发挥你的聪明才智,创造财富吧,我的傻傻的机器人在内部市场等着给大家发钱呢!

什么,你说dex 没有例子?? 如果这个还要写例子,我劝你还是别用程序玩内部市场啦。这个就当做留给大家的小作业吧。 (其实我是真的好懒,我会说吗?

全系列完,感谢阅读。


This page is synchronized from the post: 一起来玩内部市场吧(三)!/ Program trading

一起来玩内部市场吧(二)!/ Market history APIs by example

昨天发了一篇文章,《一起来玩内部市场吧!/ Let’s play the internal market》

很多朋友私下里表示了极大的兴趣,因为内部市场最吸引人的特点:没有手续费!与其去其它各类市场被人家薅羊毛,不如咱们自己在内部市场愉快的玩耍,没有手续费,考验的就是技术和运气了。

关于内部市场,我之前也写过一系列的文章,当然其实就是自己学习的过程,毕竟在这之前,我对交易什么的也一窍不通。详情可参考页面底部的之前相关文章。在这篇文章中,我来介绍一下,自动操作可能涉及到的API等。


(图源:pixabay)

本篇文章介绍以下API / In this article, I’ll introduce the following APIs by example:

  • get_ticker()
  • get_volume()
  • get_order_book()
  • get_recent_trades()
  • get_trade_history()
  • get_market_history_buckets()
  • get_market_history()

详情可以参考,market_history_api.hpp
They are located in market_history_api.hpp

API返回的结果是JSON 编码字符串,为了便于查看,我将其解码并格式化显示。
The return results are JSON encoded string, For convenience, I decode them and display them formatted.


get_ticker()

API: market_ticker get_ticker() const;
说明: 获取市场报价信息
Returns the market ticker for the internal SBD:STEEM market

调用示例 /Example:
curl -s --data '{"jsonrpc": "2.0", "method": "call", "params": ["market_history_api", "get_ticker", []], "id": 1}' https://steemd.steemit.com

返回信息 / Return:


get_volume()

API: market_volume get_volume() const;
说明: 最近24小时的时常交易量
Returns the market volume for the past 24 hours

调用示例 /Example:
curl -s --data '{"jsonrpc": "2.0", "method": "call", "params": ["market_history_api", "get_volume", []], "id": 1}' https://steemd.steemit.com

返回信息 / Return:


get_order_book()

API: order_book get_order_book( uint32_t limit = 500 ) const;
说明: 获取市场当前订单信息
Returns the current order book for the internal SBD:STEEM market.

调用示例 /Example:
curl -s --data '{"jsonrpc": "2.0", "method": "call", "params": ["market_history_api", "get_order_book", [5]], "id": 1}' https://steemd.steemit.com

返回信息 / Return:


get_recent_trades()

API: std::vector< market_trade > get_recent_trades( uint32_t limit = 1000 ) const;
说明: 获取内部市场最近成交信息
Returns the N most recent trades for the internal SBD:STEEM market.

调用示例 /Example:
curl -s --data '{"jsonrpc": "2.0", "method": "call", "params": ["market_history_api", "get_recent_trades", [5]], "id": 1}' https://steemd.steemit.com

返回信息 / Return:


get_trade_history()

API: std::vector< market_trade > get_trade_history( time_point_sec start, time_point_sec end, uint32_t limit = 1000 ) const;
说明: 获取内部市场指定时间范围内的成交信息
Returns the trade history for the internal SBD:STEEM market.

调用示例 /Example:
curl -s --data '{"jsonrpc": "2.0", "method": "call", "params": ["market_history_api", "get_trade_history", ["2016-08-01T00:00:00", "2016-08-05T00:00:00", 10]], "id": 1}' https://steemd.steemit.com

返回信息 / Return:


get_market_history_buckets()

API: flat_set< uint32_t > get_market_history_buckets() const;
说明: 获取市场行情处理区间(15秒/分钟/5分钟/等)
Returns the bucket seconds being tracked by the plugin.

调用示例 /Example:
curl -s --data '{"jsonrpc": "2.0", "method": "call", "params": ["market_history_api", "get_market_history_buckets", []], "id": 1}' https://steemd.steemit.com

返回信息 / Return:


get_market_history()

API: std::vector< bucket_object > get_market_history( uint32_t bucket_seconds, time_point_sec start, time_point_sec end ) const;
说明: 获取内部市场历史信息
Returns the market history for the internal SBD:STEEM market.

调用示例 /Example:
curl -s --data '{"jsonrpc": "2.0", "method": "call", "params": ["market_history_api", "get_market_history", [86400, "2016-08-01T00:00:00", "2016-08-05T00:00:00"]], "id": 1}' https://steemd.steemit.com

返回信息 / Return:


之前相关文章 / Previous articles


This page is synchronized from the post: 一起来玩内部市场吧(二)!/ Market history APIs by example

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×