科普 | 区块链钱包账号管理

本文简单描述钱包账号管理的一些方法。

 

一、术语

 

1.1 gas,Gas Limit和Gas Price

在墨客区块链上,发送代币或调用智能合约、执行写入操作,需要支付矿工计算费用,计费是按照Gas计算的,Gas使用moac来支付。无论调用的方法是成功还是失败,都需要支付计算费用。即使失败,矿工也验证并执行交易(计算),因此必须和成功交易一样支付矿工费。

 

Gas Limit称为限额,它是用户愿意在一笔交易中花费Gas的最大数量。交易所需的Gas是通过调用智能合约执行多少代码来定义。如果您不想花太多的Gas,通过降低Gas Limit将不会有太大的帮助。因为您必须包括足够的Gas来支付的计算资源,否则由于Gas不够导致交易失败,您所设置的所有Gas limit也将消耗光。建议您在有充足moac情况下,将Gas Limit尽量设高,所有未使用的Gas将在转账结束时退还给您。

 

通过降低Gas Price可以节省矿工费用,但是也会减慢矿工打包的速度。矿工会优先打包 Gas Price设置高的交易,如果您想加快转账,您可以把Gas Price设置得更高,这样您就可以排队靠前。如果您不急,您只需要设置一个安全的 Gas Price,矿工也会打包您的交易。

 

1.2 moac单位

moac最小的单位是sha,最常用的单位是mc。

科普 | 区块链钱包账号管理_第1张图片

 

1.3 keystore

keystore是账户的一种表现形式,里面包含了账户的地址,账户密文的私钥和MAC地址等等一系列的信息,下面是一个keystore的完整信息。

科普 | 区块链钱包账号管理_第2张图片

 

1.5 元交易

 

元交易是这样一种发送交易的模式:发送方先对一个合法的交易签名,然后把该交易和签名通过链下传递的方式转交给一个中继方,该中继方愿意承担该笔交易的 gas 费并最终发送交易到网络中。

 

这种元交易模式很有用,因为发送方不再需要在发送账户中存有moac,从用户体验角度这很有益处。

 

元交易最终的目标地址一般都是某个合约,且在某种程度上,该合约知道,交易的签名方并不是交易实际的发送者。此时,交易 API 的 msg.sender 字段会返回中继方的地址,但其很可能并没有代表签名方操作的权利,所以在这个场景下(仅仅查看 msg.sender 字段)并没有太大意义。因此,许多元交易依赖链上的签名校验(通过 API 的 ecRecover 函数)来保证签名方账户的确是在一份合适的白名单里面(有权限操作该交易想要执行的指令)。

 

1.6 其他

 

Nonce:交易计数器,即该账户主动发起的交易数量,从0开始计数。

助记词:通过算法从词库里面产生12-24个单词,目前支持多种语言。

随机种子:使用助记词通过算法产生的一个随机字符串。

私钥:钱包中最重要的东西,钱包实际上就对私钥进行管理,现在私钥有主私钥和派生私钥的说法。

主私钥:钱包私钥,由助记词产生的随机种子生成,主私钥被盗的话,你的整个钱包的钱将全部被盗。

派生私钥:由主私钥通过bip分层协议生成的私钥,派生私钥丢失,只会丢失单一账户上的数字资产。

备份钱包:其实也叫备份助记词,现在的钱包基本上都是用助记词恢复的。

备份私钥:对钱包的主私钥或者派生私钥进行备份,通过主私钥可以找回钱包中所有的账户,通过派生私钥只能找回其中的一个账户。

导入钱包:通过导入助记词或者私钥的方式生成以前的钱包。

导入私钥:通过导入私钥生成多链多账户钱包,或者单链单账户钱包。

单链钱包:只支持一条链的钱包,比方说比特币钱包。

多链钱包:支持所有币种的钱包。

单账户钱包:每种币只支持一个账户。

多账户钱包:每种币支持多个账户。

地址:类似于银行卡账户,通过地址可以查询到目前账户上的余额。

公钥:对所有人公开的秘钥。

签名:在发起数字资产转账时,所有的币种都要对转账的数据进行签名,签名的数据量对于不同的币种不一样。

空投:就是批量打币。

bip协议簇:HD分层钱包中的一个重要的规定,是数字货币发展的必然产物。

非确定性钱包:每个账户对应一个私钥,私钥不好管理。

确定性钱包:有主私钥,通过主私钥可以生产其他所有币种的私钥,但不能支持多账户。

确定性分层钱包:有主私钥,通过主私钥可以生产其他所有币种的私钥,支持多账户。

 

 

二、开源库keythereum

Keythereum是一个用于生成,导入和导出密钥的JavaScript工具。这提供了一种在本地和Web钱包中使用同一帐户的简单方法。它可用于可验证和存储钱包。

 

Keythereum使用相同的密钥派生函数(PBKDF2-SHA256或scrypt),对称密码(AES-128-CTR或AES-128-CBC)和消息验证代码。您可以将生成的密钥导出到文件,将其复制到数据目录的密钥库,然后立即开始在您的本地客户端中使用它。

 

从版本0.5.0开始,keythereum的加密和解密函数都返回Buffers而不是字符串。对于直接使用这些功能的人来说,这是一个重大改变。

 

2.1 使用keythereum生产keystore:

在生成keystore之前,你必须有一个nodeJs的环境,并且安装好keythereum。

 

或者使用压缩的浏览器文件dist/keythereum.min.js,以便在浏览器中使用。使用代码引入。

 

生成一个新的随机私钥(256位),以及密钥派生函数使用的salt(256位),用于AES-128-CTR的初始化向量(128位)对密钥进行加密。如果传递回调函数,则create是异步的,否则是同步的。

 

下面是生成keystore的代码:

科普 | 区块链钱包账号管理_第3张图片

 

运行结果:

科普 | 区块链钱包账号管理_第4张图片

 

2.2 将keystore保存到文件中:

 

dump创建一个对象而不是JSON字符串。在Node中,exportToFile方法提供了一种将此格式化的密钥对象导出到文件的简便方法。它在keystore子目录中创建一个JSON文件,并使用geth的当前文件命名约定(ISO时间戳与密钥派生的以太坊地址连接)。

 

代码如下:

科普 | 区块链钱包账号管理_第5张图片

 

成功之后在你的keystore目录下将看到一个keystore格式的账号文件,如果出现错误,最可能的原因就是你的目录下没有keystore这个目录,当然以上代码中你也可以指定keystore的存储目录。

 

2.3 keystore的导入:

 

从keystore密钥库导入密钥只能在Node上完成。将JSON文件解析为与上面的keyObject具有相同结构的对象。以下代码需要在keystore目录下已经存在keystore格式的账号文件。

科普 | 区块链钱包账号管理_第6张图片

 

运行结果:

科普 | 区块链钱包账号管理_第7张图片

 

2.4 从keystore中恢复私钥:

这里恢复出来的私钥是buffer格式的,password是你设置的密码,keyObject就是keystore。

 

 

科普 | 区块链钱包账号管理_第8张图片

运行结果:

科普 | 区块链钱包账号管理_第9张图片

 

三、开源库eth-crypto

3.1 安装

科普 | 区块链钱包账号管理_第10张图片

 

3.2 创建账号

node环境下运行以下代码,可以离线生成账号,得到私钥、公钥和地址。

 

const EthCrypto = require('eth-crypto');

 

const identity = EthCrypto.createIdentity();

 

//可以直接显示私钥、公钥和地址

console.log('privateKey:'+identity.privateKey);

console.log('publicKey: '+identity.publicKey);

console.log('address:   '+identity.address);

 

/* >  

privateKey:0xafd2fa1a57103993c16e2318f45206417c5cf840bb204603912b8dc54b7d8800

publicKey: 37b7d6b1b7bc05947d42ecfd3b63dee6cd54ff3ebfd5c6637f3224f45d05c2f4ad0b8ffea1abd2c2313965662cfd7a09e2c9dd683eec4eeab4b19838e01b9f1c

address:   0x16F119734F845a5348dd37175ca81059E66C90B3

*/

 

3.3 从私钥得到公钥

 

const EthCrypto = require('eth-crypto');

var privateKey  = "0xafd2fa1a57103993c16e2318f45206417c5cf840bb204603912b8dc54b7d8800";

 

//从私钥得到公钥

const publicKey = EthCrypto.publicKeyByPrivateKey(privateKey);

console.log('publicKeyByPrivateKey: '+publicKey); 

 

/* >       

publicKeyByPrivateKey: 37b7d6b1b7bc05947d42ecfd3b63dee6cd54ff3ebfd5c6637f3224f45d05c2f4ad0b8ffea1abd2c2313965662cfd7a09e2c9dd683eec4eeab4b19838e01b9f1c

*/

 

3.4 从公钥得到地址

 

const EthCrypto = require('eth-crypto');

const publicKey = "37b7d6b1b7bc05947d42ecfd3b63dee6cd54ff3ebfd5c6637f3224f45d05c2f4ad0b8ffea1abd2c2313965662cfd7a09e2c9dd683eec4eeab4b19838e01b9f1c";

 

//从公钥得到地址

const address = EthCrypto.publicKey.toAddress(publicKey);

console.log('addressByPublicKey: '+address); 

 

/* >       

addressByPublicKey: 0x16F119734F845a5348dd37175ca81059E66C90B3

*/

 

3.5 签名

const EthCrypto = require('eth-crypto');

const privateKey  = "0xafd2fa1a57103993c16e2318f45206417c5cf840bb204603912b8dc54b7d8800";

const message = 'hello,world!';

const messageHash = EthCrypto.hash.keccak256(message);

 

const signature = EthCrypto.sign(privateKey,messageHash);

console.log('signature: ' + signature); 

 

/*

signature: 0x6f9188a50f13d75fd64df378f11b025a48f089f1d51d60264e84f3690d9fd6c6117abff827b06ab9de98e9c2837d6d9a6451ed113cf4492c8e28a4e2bd377bf51c

*/

 

3.6 从签名信息获得地址

此处需要知道明文信息。

const EthCrypto = require('eth-crypto');

const signature = "0x6f9188a50f13d75fd64df378f11b025a48f089f1d51d60264e84f3690d9fd6c6117abff827b06ab9de98e9c2837d6d9a6451ed113cf4492c8e28a4e2bd377bf51c";

 

const signer = EthCrypto.recover(signature,EthCrypto.hash.keccak256('hello,world!'));

console.log('signer: ' + signer);

 

/*

signer: 0x16F119734F845a5348dd37175ca81059E66C90B3

*/

 

 

3.7 从签名信息获得公钥

此处需要知道明文信息。

 

const EthCrypto = require('eth-crypto');

const signature = "0x6f9188a50f13d75fd64df378f11b025a48f089f1d51d60264e84f3690d9fd6c6117abff827b06ab9de98e9c2837d6d9a6451ed113cf4492c8e28a4e2bd377bf51c";

 

const signer = EthCrypto.recoverPublicKey(signature,EthCrypto.hash.keccak256('hello,world!'));

console.log('signer: ' + signer);

 

/*

signer: 37b7d6b1b7bc05947d42ecfd3b63dee6cd54ff3ebfd5c6637f3224f45d05c2f4ad0b8ffea1abd2c2313965662cfd7a09e2c9dd683eec4eeab4b19838e01b9f1c

*/

 

 

四、交易

 

4.1交易确认

 

并不是我们查询区块链中的交易就说明这笔交易已经成功了,墨客是默认确认12次之后,此交易几乎不会被篡改,那么怎么计算确认次数呢?

 

确认次数 = 当前区块高度 - 交易所在区块高度 + 1

 

此处注意事项:交易有可能会被孤立,在执行此公式时需要验证一下区块中此交易是否还是在那个区块上,是否已经被回滚。

 

交易的gas费算是常识性的内容,可给用户一些参考值,让用户选择愿意支付的手续费。最笨拙而又有效的方法是定期观察一下区块链上交易成功的交易的 gasPrice 的大概范围,动态的调整一下价格,而 gasLimit 在不影响交易的情况下,尽可能稍微多一些,因为此部分如果未使用还会退换到交易发起账户中。

 

4.2交易中nonce维护

 

转账地址的合法性检查,此合法性检查可以避免后续很多问题的出现,比如 nonce 值的维护。

交易的金额检查,nonce 值检查(nonce 值会遇到的问题前面已经提到过),特别是私钥与节点分离之后自己来维护私钥时 nonce 值会是一个很大的问题,比如前一笔交易失败,nonce 值需要回退,此时后一笔交易已经发出,因为前一笔 nonce 没有被补齐,后一笔迟迟不会被交易。这些都需要业务进行特殊判断和处理。

查询一个地址 nonce,mc.getTransactionCount。

 

4.3交易记录

 

只能通过遍历区块交易的方法来判断是否有对应账户的交易。相关操作步骤主要包括:

 

*查询区块高度,比对是否是新生成的区块,mc.blockNumber;

*查看区块内容及详细交易,mc.gethBlock;

*比对交易的 toAddress 是否为本钱包的地址,如果是则记录此笔交易到数据库,并记录交易状态(确认次数等);

*保证入库和记账的幂等性,因为会多次查询到同一笔交易;

*作为钱包开发来说,实际需要解析所有交易,并保存到数据库备查。

 

你可能感兴趣的:(科普 | 区块链钱包账号管理)