今天来了解下Bitshares怎么实现修改帐户密钥,还有帐户模式下怎么修改密码。
Bitshares钱包
Bitshares钱包提供修改密钥功能,可以对资金权限、帐户权限、备注密钥和帐号模式的密码进行修改,如下图:
“帐号模式”仅使用密码就能从任何地方(包括不同浏览器,不同的钱包提供网站)登录自己的账户,比较方便。在“帐号模式登录”中设置密码,密码至少要12位,在下方会生成资金密钥、帐户密钥、备注密钥,可以点击密钥右方的“使用”来确认哪个密钥有效,然后再点击上方“保存修改”,输入密码后才能修改完成。如下图:
再回“资金权限”项就可以看到,资金权限的公钥增加了一个,如下图:
可以看到通过Bitshares钱包,可以手动设置各个权限的公私钥,也可以修改帐号模式的密码,帐号模式的密码修改完成后原有密钥并不会删除,需要自己到权限页面中手动删除。
但是这个地方一定要注意几个事情:
- 别把密钥全移除了,如果是帐户权限全移除的话这个帐户就作废了;
- 权重/阈值想清楚了再设,一旦设错可能再也无法操作。
简单点说就是可以随便增加,但别随便删除和调整权重/阈值!
我一朋友就用多重签名把终身会员帐户给弄废了,因为设了必须两个帐户同意才能操作,而另一个帐户是别人的,但别人的密码密钥都没有了!当然我也有个帐户barnard19把自己的owner权限删除了,在owner权限中加上了另一帐号,不过这个应该还有点办法,等理清了再看看怎么恢复!
更详细权限说明传送门:Bitshares的权限参考和多重签名
密钥修改分析
密钥数据结构
get_account barnard20
{
"id": "1.2.879822",
"membership_expiration_date": "1970-01-01T00:00:00",
"registrar": "1.2.450921",
"referrer": "1.2.450921",
"lifetime_referrer": "1.2.450921",
"network_fee_percentage": 2000,
"lifetime_referrer_fee_percentage": 3000,
"referrer_rewards_percentage": 7000,
"name": "barnard20",
"owner": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [[
"BTS5e9Mnf2n1ExHwZVWixJr3FS5VasZG9jNRB4Yh4mFFJuW7xHg1R",
1
],[
"BTS6psUtCCC3gg6xoDVemGGmAQta2cU8BTBQVFLwGHaQJTZjcP4s3",
1
]
],
"address_auths": []
},
"active": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [[
"BTS8EdfKXbmNrzcngwZBZpUrTNotsFGFWTRKpNaBpcGRrx4Qrqcz6",
1
],[
"BTS6KarQcA5MYBBTJ6xHWqBx2r1XSKxYy6YXytM8T8MW5CTsV8agh",
1
]
],
"address_auths": []
},
"options": {
"memo_key": "BTS8EdfKXbmNrzcngwZBZpUrTNotsFGFWTRKpNaBpcGRrx4Qrqcz6",
"voting_account": "1.2.5",
"num_witness": 0,
"num_committee": 0,
"votes": [],
"extensions": []
},
从以上json数据可以看到资金权限和帐户权限可以有3种不同的方式控制:帐号、密钥、地址,每种方式都可以有多个帐号/密钥/地址,而memo密钥只能有1个,这个是因为memo加密是要用双方公钥,多个memo密钥就乱了,见bitshares研究系列【memo加解密】
代码实现
密钥修改其实就是对帐号信息的修改,通过 account_update_operation 实现,如下:
void_result account_update_evaluator::do_apply( const account_update_operation& o )
{ try {
database& d = db();
bool sa_before, sa_after;
d.modify( *acnt, [&](account_object& a){
if( o.owner )
{
a.owner = *o.owner;
a.top_n_control_flags = 0;
}
if( o.active )
{
a.active = *o.active;
a.top_n_control_flags = 0;
}
...
}
这个修改只是简单的赋值,取决于请求的数据。
bitshares钱包修改帐号密码是先增加密钥,需要用户再手动删除,从代码来看应该是可以删除和增加同时操作的,来试一下。
不过修改帐户密钥没有cli_wallet方法,只能直连节点发送operation命令来完成,用python-utransnet库,但只提供了allow、disallow方法,没有替换接口,增加一个changeallow,如下:
def changeallow(
self, foreign, changed, weight=None, permission="active",
account=None, threshold=None, **kwargs
):
""" Remove additional access to an account by some other public
key or account.
:param str foreign: The foreign account that will obtain access
:param str permission: (optional) The actual permission to
modify (defaults to ``active``)
:param str account: (optional) the account to allow access
to (defaults to ``default_account``)
:param int threshold: The threshold that needs to be reached
by signatures to be able to interact
"""
if not account:
if "default_account" in config:
account = config["default_account"]
if not account:
raise ValueError("You need to provide an account")
if permission not in ["owner", "active"]:
raise ValueError(
"Permission needs to be either 'owner', or 'active"
)
account = Account(account, transnet_instance=self)
authority = account[permission]
print("prefix:" + str(self.prefix))
try:
pubkey = PublicKey(foreign, prefix=self.prefix)
print("foreign pubkey:" + str(pubkey))
affected_items = list(
filter(lambda x: x[0] == str(pubkey),
authority["key_auths"]))
authority["key_auths"] = list(filter(
lambda x: x[0] != str(pubkey),
authority["key_auths"]
))
except:
try:
foreign_account = Account(foreign, transnet_instance=self)
affected_items = list(
filter(lambda x: x[0] == foreign_account["id"],
authority["account_auths"]))
authority["account_auths"] = list(filter(
lambda x: x[0] != foreign_account["id"],
authority["account_auths"]
))
except:
raise ValueError(
"Unknown foreign account or unvalid public key"
)
if not affected_items:
raise ValueError("Changes nothing!")
removed_weight = affected_items[0][1]
if not weight:
weight = account[permission]["weight_threshold"]
from copy import deepcopy
authority = deepcopy(account[permission])
try:
pubkey = PublicKey(changed, prefix=self.prefix)
authority["key_auths"].append([
str(pubkey),
weight
])
except:
try:
foreign_account = Account(changed, transnet_instance=self)
authority["account_auths"].append([
foreign_account["id"],
weight
])
except:
raise ValueError(
"Unknown foreign account or invalid public key"
)
# Define threshold
if threshold:
authority["weight_threshold"] = threshold
# Correct threshold (at most by the amount removed from the
# authority)
try:
self._test_weights_treshold(authority)
except:
log.critical(
"The account's threshold will be reduced by %d"
% (removed_weight)
)
authority["weight_threshold"] -= removed_weight
self._test_weights_treshold(authority)
op = operations.Account_update(**{
"fee": {"amount": 0, "asset_id": "1.3.0"},
"account": account["id"],
permission: authority,
"extensions": {}
})
if permission == "owner":
return self.finalizeOp(op, account["name"], "owner", **kwargs)
else:
return self.finalizeOp(op, account["name"], "active", **kwargs)
调用方法:
r = transnet.changeallow("BTS6KarQcA5MYBBTJ6xHWqBx2r1XSKxYy6YXytM8T8MW5CTsV8agh", "BTS8EXUV2yr1VoSL1r3eDckbE4WB5K6o6YTKjiRK6Zyh6jXFaC7c8", account="barnard20")
执行成功,这样就把“BTS6KarQcA5MYBBTJ6xHWqBx2r1XSKxYy6YXytM8T8MW5CTsV8agh”替换成“BTS8EXUV2yr1VoSL1r3eDckbE4WB5K6o6YTKjiRK6Zyh6jXFaC7c8”了。
结论
帐户密码是可以直接替换的,能把增加、删除两步操作合到一块,除了增加响应速度,省那么一点燃料费之外,可能还有些其它用处!
感谢您阅读 @chaimyu 的帖子,期待您能留言交流!