当前位置: 代码网 > it编程>App开发>Android > 区块链钱包开发(Android篇),深入解析android核心组件和应用框架

区块链钱包开发(Android篇),深入解析android核心组件和应用框架

2024年08月02日 Android 我要评论
作用:1、备份更容易。按照比特币的原则,尽量不要使用同一个地址,一个地址只使用一次,这样会导致频繁备份钱包。HD钱包只需要在创建时保存主密钥,通过主密钥可以派生出所有的子密钥。2、私钥离线更安全。主私钥离线存储,主公钥在线使用,通过主公钥可以派生出所有的子公钥。例如:给每个商品提供一个收款地址。3、利于管理,权限控制。树状结构类似于公司的组织架构,可以给各个部门指定一个密钥分支。4、记账。只使用公钥即可记账。

作用:

  • 1、备份更容易。按照比特币的原则,尽量不要使用同一个地址,一个地址只使用一次,这样会导致频繁备份钱包。hd钱包只需要在创建时保存主密钥,通过主密钥可以派生出所有的子密钥。

  • 2、私钥离线更安全。主私钥离线存储,主公钥在线使用,通过主公钥可以派生出所有的子公钥。例如:给每个商品提供一个收款地址。

  • 3、利于管理,权限控制。树状结构类似于公司的组织架构,可以给各个部门指定一个密钥分支。

  • 4、记账。只使用公钥即可记账。

bip39

bip39:将seed 用方便记忆和书写的单字表示。一般由 12 个单字组成,称为 mnemonic code(phrase),中文称为助记词或助记码。例如: average green proud remember advance trick estate oblige trouble when cube person

wordlists

工具

bip43

bip43

bip43对bip32树结构增加了子索引标识purpose的拓展m/purpose’/*

bip32的索引:m/0’/*

bip44的索引:m/44’/*。

bip44

bip44:基于bip32和bip43,赋予树状结构中的各层特殊的意义。让同一个 seed 可以支援多币种、多帐户等。各层定义如下:

m / purpose’ / coin_type’ / account’ / change / address_index

  • purporse’: 固定值44’, 代表是bip44
  • coin_type’: 这个代表的是币种, 可以兼容很多种币, 比如btc是0’, eth是60’, 例如:btc一般是 m/44’/0’/0’/0, eth一般是 m/44’/60’/0’/0
  • account’:账号
  • change’: 0表示外部链(external chain),用户接收比特币,1表示内部链(internal chain),用于接收找零
  • address_index:钱包索引

钱包最佳实践

  • 使用助记词(bip39)
  • 使用层级确定性钱包(hd wallets)(bip32)
  • 使用多目的hd wallets(bip43)
  • 使用多币种,多账号的hd wallets (bip44)

比特币钱包地址创建过程

1、生成128bit~256bit作为私钥

2、通过secp256k1椭圆曲线算法得到私钥对应的公钥

3、将公钥进行sha-256,得到公钥hash

4、将3的结果进行rimemd-160

5、将4中结果添加1个字节版本号

6、将5中结果进行两次sha-256,取前4个字节作为checksum

7、将6中结果添加到5中结果的末尾

8、将7中结果进行base58,结果为比特币地址

bitcoinj创建钱包

bitcoinj是比特币协议java版本实现的库。

添加依赖:

dependencies {
implementation ‘org.bitcoinj:bitcoinj-core:0.14.7’
implementation ‘org.slf4j:slf4j-api:1.7.25’
implementation ‘com.squareup.okhttp3:okhttp:3.10.0’
implementation ‘com.squareup.okhttp3:logging-interceptor:3.10.0’
implementation ‘com.google.zxing:core:3.3.3’//二维码
}

android最大方法数的限制,60k 开启multidexenabled

android {
compilesdkversion 28
defaultconfig {
multidexenabled true
}
}

dependencies {
implementation ‘com.android.support:multidex:1.0.3’
}

创建新钱包

file walletfile = activity.getfilestreampath(“wallet-protobuf”);
//创建钱包
wallet = new wallet(constants.network_parameters);
//创建walletfiles,设置自动保存wallet
walletfiles walletfiles = wallet.autosavetofile(walletfile, 3 * 1000, timeunit.milliseconds, null);
//立即保存
walletfiles.savenow();

钱包创建源码分析:

  • wallet

  • keychaingroup

  • deterministickeychain

  • deterministicseed

protected deterministickeychain(deterministicseed seed, @nullable keycrypter crypter) {
this.seed = seed;
basickeychain = new basickeychain(crypter);
if (!seed.isencrypted()) {
rootkey = hdkeyderivation.createmasterprivatekey(checknotnull(seed.getseedbytes()));
rootkey.setcreationtimeseconds(seed.getcreationtimeseconds());
addtobasicchain(rootkey);
hierarchy = new deterministichierarchy(rootkey);
for (int i = 1; i <= getaccountpath().size(); i++) {
addtobasicchain(hierarchy.get(getaccountpath().sublist(0, i), false, true));
}
initializehierarchyunencrypted(rootkey);
}
// else…
// we can’t initialize ourselves with just an encrypted seed, so we expected deserialization code to do the
// rest of the setup (loading the root key).
}

获取钱包地址

address address = wallet.currentaddress(keychain.keypurpose.receive_funds);
address.tostring();

在获取地址的过程中会调用rimemd-160算法处理公钥hash:

//utils.java
public static byte[] sha256hash160(byte[] input) {
byte[] sha256 = sha256hash.hash(input);
ripemd160digest digest = new ripemd160digest();
digest.update(sha256, 0, sha256.length);
byte[] out = new byte[20];
digest.dofinal(out, 0);
return out;
}

处理公钥hash后会进行base58算法:

//versionedchecksummedbytes.java
public final string tobase58() {
// a stringified buffer is:
// 1 byte version + data bytes + 4 bytes check code (a truncated hash)
byte[] addressbytes = new byte[1 + bytes.length + 4];
addressbytes[0] = (byte) version;
system.arraycopy(bytes, 0, addressbytes, 1, bytes.length);
byte[] checksum = sha256hash.hashtwice(addressbytes, 0, bytes.length + 1);
system.arraycopy(checksum, 0, addressbytes, bytes.length + 1, 4);
return base58.encode(addressbytes);
}

从文件中加载钱包

//读取钱包文件
file walletfile = activity.getfilestreampath(“wallet-protobuf”);
if (walletfile.exists()) {
inputstream inputstream = new fileinputstream(walletfile);
//反序列化
wallet = new walletprotobufserializer().readwallet(inputstream);
//设置自动保存
wallet.autosavetofile(walletfile, 3 * 1000, timeunit.milliseconds, null);
//清理钱包
wallet.cleanup();
}

创建地址二维码

string s = bitcoinuri.converttobitcoinuri(address, null, null, null);
bitmap bitmap = qr.bitmap(s);
bitmapdrawable bitmapdrawable = new bitmapdrawable(getresources(), bitmap);
bitmapdrawable.setfilterbitmap(false);
mqrimageview.setimagedrawable(bitmapdrawable);

public static bitmap bitmap(final string content) {
try {
final hashtable<encodehinttype, object> hints = new hashtable<encodehinttype, object>();
hints.put(encodehinttype.margin, 0);
hints.put(encodehinttype.error_correction, errorcorrectionlevel.h);
final bitmatrix result = qr_code_writer.encode(content, barcodeformat.qr_code, 0, 0, hints);

final int width = result.getwidth();
final int height = result.getheight();
final byte[] pixels = new byte[width * height];

for (int y = 0; y < height; y++) {
final int offset = y * width;
for (int x = 0; x < width; x++) {
pixels[offset + x] = (byte) (result.get(x, y) ? -1 : 0);
}
}

final bitmap bitmap = bitmap.createbitmap(width, height, bitmap.config.alpha_8);
bitmap.copypixelsfrombuffer(bytebuffer.wrap(pixels));
return bitmap;
} catch (final writerexception x) {
log.info(“problem creating qr code”, x);
return null;
}
}

bitcoin钱包收款和转账

比特币钱包余额需要统计所有钱包地址对应的utxo

simplified payment verification (spv):节点无需下载所有的区块数据,而只需要加载所有区块头数据(block header的大小为80b),即可验证这笔交易是否曾经被比特币网络认证过。

布隆过滤器(bloom filter):过滤掉那些不包含有目标地址的交易信息,这一步能避免掉大量不相关的数据下载。

创建区块链

//创建区块链文件
file blockchainfile = new file(getdir(“blockstore”, context.mode_private), “blockchain”);
//创建spvblockstore,管理区块数据
blockstore = new spvblockstore(constants.network_parameters, blockchainfile);
//加载检查点
final inputstream checkpointsinputstream = getassets().open(“checkpoints-testnet.txt”);
checkpointmanager.checkpoint(constants.network_parameters, checkpointsinputstream,
blockstore, earliestkeycreationtime);
//创建区块链对象
blockchain = new blockchain(constants.network_parameters, wallet, blockstore);

同步区块链

//添加网络权限:

private void startup() {
log.d(tag, "startup: ");
peergroup = new peergroup(constants.network_parameters, blockchain);
peergroup.setdownloadtxdependencies(0); // recursive implementation causes stackoverflowerror
peergroup.addwallet(wallet);//设置钱包,重要
try {
packageinfo packageinfo = getpackagemanager().getpackageinfo(getpackagename(), packagemanager.get_activities);
peergroup.setuseragent(user_agent, packageinfo.versionname);
} catch (packagemanager.namenotfoundexception e) {
e.printstacktrace();
}
peergroup.setmaxconnections(8);
int connecttimeout = (int) (15 * dateutils.second_in_millis);
peergroup.setconnecttimeoutmillis(connecttimeout);
int discoverytimeout = (int) (10 * dateutils.second_in_millis);
peergroup.addconnectedeventlistener(mpeerconnectedeventlistener);
peergroup.adddisconnectedeventlistener(mpeerdisconnectedeventlistener);
peergroup.adddiscoveredeventlistener(mpeerdiscoveredeventlistener);
peergroup.setpeerdiscoverytimeoutmillis(discoverytimeout);

//添加节点探索器,重要
peergroup.addpeerdiscovery(new peerdiscovery() {
private final peerdiscovery normalpeerdiscovery = multiplexingdiscovery
.forservices(constants.network_parameters, 0);

@override
public inetsocketaddress[] getpeers(final long services, final long timeoutvalue,
final timeunit timeoutunit) throws peerdiscoveryexception {
return normalpeerdiscovery.getpeers(services, timeoutvalue, timeoutunit);
}

@override
public void shutdown() {
normalpeerdiscovery.shutdown();
}
});
peergroup.startasync();
peergroup.startblockchaindownload(null);
}

比特币收款

获取测试用比特币:testnet.manu.backend.hamburg/faucet 刚收到的币可能需要几分钟后才能使用

//监听比特币接受事件
wallet.addcoinsreceivedeventlistener(mwalletlistener);
//刷新余额
coin balance = wallet.getbalance(wallet.balancetype.estimated);

比特币转账

比特币测试链转账查询 创建一个tx,对tx进行签名,对tx进行p2p网络广播

address address = address.frombase58(constants.network_parameters, to);
//转账金额,以mbtc为单位
coin coin = monetaryformat.mbtc.parse(amount);
//创建请求
sendrequest sendrequest = sendrequest.to(address, coin);
try {
//创建transaction
transaction transaction = wallet.sendcoinsoffline(sendrequest);
//通过p2p广播
blockchainservice.broadcasttransaction(bitcoinwalletactivity.this, transaction);
} catch (insufficientmoneyexception e) {
toast.maketext(this, e.getlocalizedmessage(), toast.length_short).show();
e.printstacktrace();
}

public static void broadcasttransaction(context context, transaction transaction) {
intent intent = new intent(action_broadcast_transaction, null, context, blockchainservice.class);
intent.putextra(action_broadcast_transaction_hash, transaction.gethash().getbytes());
context.startservice(intent);
}

@override
public int onstartcommand(intent intent, int flags, int startid) {
log.d(tag, "onstartcommand: ");
if (intent != null) {
byte[] txhash = intent.getbytearrayextra(“tx”);
if (txhash != null) {
sha256hash sha256hash = sha256hash.wrap(txhash);
transaction transaction = bitcoinwalletmanager.getinstance().getwallet().gettransaction(sha256hash);
peergroup.broadcasttransaction(transaction);
log.d(tag, "onstartcommand: " + sha256hash.tostring());
}
}
return super.onstartcommand(intent, flags, startid);
}

以太坊钱包

github.com/ethereumboo…

以太坊钱包功能与比特币钱包功能类似,获取用户余额,管理地址和密钥,转账、智能合约调用。以太坊钱包一般不用在本地维护区块链数据,只需要使用json-rpc访问

钱包文件

keystore = 私钥 + 密码

如果使用imtoken创建钱包,创建了助记词,密码用来加密钱包地址对应的子私钥,加密的结果就是keystore.

{
“address”: “001d3f1ef827552ae1114027bd3ecf1f086ba0f9”,
“crypto”: {
“cipher”: “aes-128-ctr”,
“ciphertext”: “233a9f4d236ed0c13394b504b6da5df02587c8bf1ad8946f6f2b58f055507ece”,
“cipherparams”: {

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、oppo等大厂,18年进入阿里一直到现在。

深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面v无偿领取!(备注android)
img

学习分享,共勉

android高级架构师进阶之路

题外话,我在阿里工作多年,深知技术改革和创新的方向,android开发以其美观、快速、高效、开放等优势迅速俘获人心,但很多android兴趣爱好者所需的进阶学习资料确实不太系统,完整。今天我把我搜集和整理的这份学习资料分享给有需要的人,若有关android学习进阶可以与我在android终极开发交流群一起讨论交流。 点击这里前往我的git领取资料 的同时,还可以加入一个好的学习交流圈,何乐而不为呢?加入我们和我们一起吧!!

  • android进阶知识体系学习脑图

  • android进阶高级工程师学习全套手册

  • 对标android阿里p7,年薪50w+学习视频

  • 大厂内部android高频面试题,以及面试经历

分享给有需要的人,若有关android学习进阶可以与我在android终极开发交流群一起讨论交流。 点击这里前往我的git领取资料 的同时,还可以加入一个好的学习交流圈,何乐而不为呢?加入我们和我们一起吧!!

  • android进阶知识体系学习脑图

[外链图片转存中…(img-htdcct7g-1710901256682)]

  • android进阶高级工程师学习全套手册

[外链图片转存中…(img-b11dcjod-1710901256682)]

  • 对标android阿里p7,年薪50w+学习视频

[外链图片转存中…(img-bypqlhfb-1710901256682)]

  • 大厂内部android高频面试题,以及面试经历

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com