文档章节

Java实现一个简单的比特币系统

轻风吟
 轻风吟
发布于 04/08 14:30
字数 2149
阅读 1063
收藏 32

最近区块链技术突然爆火,身边做技术的朋友茶余饭后无不谈点区块链或比特币的,为啥会这样了?这其实跟比特币价格去年的突飞猛涨是分不开的,比特币价格从去年初不到一千美金到今年初最高接近两万美金,赚钱效应已经足够博取大家眼球了,吃瓜群众对比特币价格一年上涨20倍早已目瞪狗呆,个个备足钱袋,跃跃越试。可是,细问一下这些做技术的朋友比特币到底是个什么东西,它是如何构造出来的,能从技术角度解释下比特币吗,还真没几个能答得上来的,作为技术出身的我今天就来带大家用Java语言实现一个简单的比特币系统,学完之后相信上面那几个问题也就能对答如流了

区块链

比特币是构建在区块链技术之上的一个加密数字货币,区块链顾名思义即由很多区块组成的链条,可以把区块链简单比喻为一本账本,把区块比喻为账本的一页记录,账本的每一页里都记录了很多比特币的转账交易,那根据这个账本里的所有交易记录应该是能算出任何一个交易者的余额,我们先来构造一个区块的结构:

/**
 * 区块结构
 * @author aaron
 */
public class Block {
	/**
	 * 区块索引号
	 */
	private int index;
	/**
	 * 当前区块的hash值,区块唯一标识
	 */
	private String hash;
	/**
	 * 生成区块的时间戳
	 */
	private long timestamp;
	/**
	 * 当前区块的交易集合
	 */
	private List<Transaction> transactions;
	/**
	 * 工作量证明,计算正确hash值的次数
	 */
	private int nonce;
	/**
	 * 前一个区块的hash值
	 */
	private String previousHash;

	public Block() {
		super();
	}

	public Block(int index, long timestamp, List<Transaction> transactions, int nonce, String previousHash, String hash) {
		super();
		this.index = index;
		this.timestamp = timestamp;
		this.transactions = transactions;
		this.nonce = nonce;
		this.previousHash = previousHash;
		this.hash = hash;
	}
}

交易

转账交易即比特币的拥有方之间进行的相互转账行为,我们把这些比特币的拥有方暂时假设为比特币的钱包,钱包有对应的钱包地址,那这些转账交易实际上就是钱包地址之间的转账交易(类似于支付宝用户之间的转账,其实就是支付宝用户名之间的转账),这些转账交易需要被记录到账本里才算真正的生效。

由于比特币的转账交易设计比较复杂,我们今天暂时不深入讨论,所以这里我设计了一个简单的交易模型如下:

/**
 * 交易
 * @author aaron
 */
public class Transaction {
	/**
	 * 交易唯一标识
	 */
	private String id;
	/**
	 * 交易发送方钱包地址
	 */
	private String sender;
	/**
	 * 交易接收方钱包地址
	 */
	private String recipient;
	/**
	 * 交易金额
	 */
	private int amount;

	public Transaction() {
		super();
	}

	public Transaction(String id, String sender, String recipient, int amount) {
		super();
		this.id = id;
		this.sender = sender;
		this.recipient = recipient;
		this.amount = amount;
	}
}

挖矿

挖矿到底是怎么回事?为什么那么多人吵着要去挖矿,梦想着一夜暴富?

我们可以简单的把挖矿比喻成矿工解一道数学难题的过程,只要解对了就能获取比特币系统奖励的一笔比特币,同时获取了区块链账本新区块的交易记账权,矿工会把比特币系统近期发生的转账交易记录到账本新的一页上,并获取交易的手续费,一旦交易被记录进了账本,交易就算完成了,接收方才能真正收到发送方转账的比特币。那这道数学难题到底长什么样了?

我们看下这个公式:

Hash = SHA-256(区块链的最后一个区块的Hash + 需记账交易记录信息 + 随机数)

这个公式已经很明白了,SHA-256是一种哈希加密算法,被加密的前两部分是固定不变的,我们只有依赖于随机数的不断变化计算出不同的hash结果,系统要求hash结果必须要以10个0开头,这个几率实在是太小太小,我们做测试可以简单一点,比如只要hash结果满足以4个0开头,我们就认为解题成功,即挖矿成功了,这时矿工就可以生成一个新的区块把需记账的交易记录全部记录进区块里去,同时再构造一笔系统奖励给自己的比特币的交易(发起方为系统,接收方为矿工,比特币金额假设为10个),将其也记录进账本,这样通过账本里的交易记录就会发现矿工的余额多了10个比特币了,我们看下挖矿的代码:

/**
 * 挖矿
 * @param blockchain 整个区块链
 * @param txs 需记账交易记录
 * @param address 矿工钱包地址
 * @return
 */
private static void mineBlock(List<Block> blockchain, List<Transaction> txs, String address) {
	//加入系统奖励的交易,默认挖矿奖励10个比特币
	Transaction sysTx = new Transaction(CryptoUtil.UUID(), "", address, 10);
	txs.add(sysTx);
	//获取当前区块链里的最后一个区块
    	Block latestBlock = blockchain.get(blockchain.size() - 1);
	//随机数
	int nonce = 1;
	String hash = "";
	while(true){
		hash = CryptoUtil.SHA256(latestBlock.getHash() + JSON.toJSONString(txs) + nonce);
		if (hash.startsWith("0000")) {
	        System.out.println("=====计算结果正确,计算次数为:" +nonce+ ",hash:" + hash);
	        break;
        }
		nonce++;
		System.out.println("计算错误,hash:" + hash); 
	}
	
	//解出难题,可以构造新区块并加入进区块链里
	Block newBlock = new Block(latestBlock.getIndex() + 1, System.currentTimeMillis(), txs, nonce, latestBlock.getHash(), hash);
	blockchain.add(newBlock);
	System.out.println("挖矿后的区块链:" + JSON.toJSONString(blockchain));
}

余额

计算某个钱包地址的余额其实就是从区块链账本里找出所有该地址作为接收方的交易记录,将这些交易记录的发生金额累加就得到该地址收到的所有比特币金额了,然后找出所有该地址作为发送方的交易记录再次累加则得到改地址发送出去的所有比特币金额了,用收到的比特币金额之和减去发送出去的比特币金额之和就得到该地址的真正的比特币余额了,具体我们看下代码:

/**
 * 查询余额
 * @param blockchain
 * @param address
 * @return
 */
public static int getWalletBalance(List<Block> blockchain, String address) {
	int balance = 0;
	for (Block block : blockchain) {
        	List<Transaction> transactions = block.getTransactions();
        	for (Transaction transaction : transactions) {
            		if (address.equals(transaction.getRecipient())) {
            			balance += transaction.getAmount();
            		}
            		if (address.equals(transaction.getSender())) {
            			balance -= transaction.getAmount();
            		}
        	}
   	 }
	return balance;
}

系统入口

最后,我们看下这个小比特币系统的运行效果,main函数代码如下:

public static void main(String[] args) {
	//创建一个空的区块链
	List<Block> blockchain = new ArrayList<>();
	//生成创世区块
	Block block = new Block(1, System.currentTimeMillis(), new ArrayList<Transaction>(), 1, "1", "1");
	//加入创世区块到区块链里
	blockchain.add(block);
	System.out.println(JSON.toJSONString(blockchain));
	
	// 发送方钱包地址
	String sender = "sender_wallet";
	//接收方钱包地址
	String recipient = "recipient_wallet";
	
	//创建一个空的交易集合
	List<Transaction> txs = new ArrayList<>();
	//挖矿
	mineBlock(blockchain, txs, sender);
	System.out.println(sender + "钱包的余额为:" + getWalletBalance(blockchain, sender));
	
	//创建一个空的交易集合
	List<Transaction> txs1 = new ArrayList<>();
	//已发生但未记账的交易记录,发送者给接收者转账3个比特币
	Transaction tx1 = new Transaction(CryptoUtil.UUID(), sender, recipient, 3);
	//已发生但未记账的交易记录,发送者给接收者转账1个比特币
	Transaction tx2 = new Transaction(CryptoUtil.UUID(), sender, recipient, 1);
	txs1.add(tx1);
	txs1.add(tx2);
	//挖矿
	mineBlock(blockchain, txs1, sender);
	System.out.println(sender + "钱包的余额为:" + getWalletBalance(blockchain, sender));
	System.out.println(recipient + "钱包的余额为:" + getWalletBalance(blockchain, recipient));
}

运行结果如下图所示:

至此,我们就用java语言基于区块链账本技术实现了一个简单的比特币系统,包含区块链功能,挖矿产生新比特币功能,转账交易功能,查询余额功能,完整的代码可以扫描下方二维码关注微信公号"轻风吟"回复'比特币'获取

当然,真正的比特币系统远不止这么简单,比如运用密码学生成比特币钱包与保证交易信息不被篡改,运用P2P通讯技术实现点对点分布式网络等功能,我们这里只是抛砖引玉,想要深入学习的朋友们可以持续关注微信公众号"轻风吟"

© 著作权归作者所有

共有 人打赏支持
轻风吟
粉丝 13
博文 5
码字总数 11450
作品 0
浦东
私信 提问
加载中

评论(9)

geek12345
geek12345
刚写的java比特币开发教程,请楼主指教:

http://xc.hubwiz.com/course/5bb35c90c02e6b6a59171df0?affid=108oschina
CQCQCQY
CQCQCQY

引用来自“木九天”的评论

CryptoUtil.SHA256?这是工具类?

引用来自“轻风吟”的评论

是的,我的代码里有

引用来自“木九天”的评论

你的代码在哪里啊
你好,有作者的完整代码吗?
CQCQCQY
CQCQCQY
你好,公众号那里没有回复耶?
木九天
木九天

引用来自“木九天”的评论

CryptoUtil.SHA256?这是工具类?

引用来自“轻风吟”的评论

是的,我的代码里有
你的代码在哪里啊
轻风吟
轻风吟

引用来自“木九天”的评论

CryptoUtil.SHA256?这是工具类?
是的,我的代码里有
木九天
木九天
CryptoUtil.SHA256?这是工具类?
轻风吟
轻风吟

引用来自“只道寻常”的评论

如果学习区块链是因为ICO概念火,那就错了。现在的区块链技术就像93年互联网刚刚兴起,现在即是未来
明白人
只道寻常
只道寻常
如果学习区块链是因为ICO概念火,那就错了。现在的区块链技术就像93年互联网刚刚兴起,现在即是未来
geek12345
geek12345
推荐个区块链新手入门的以太坊DApp开发教程:
http://xc.hubwiz.com/course/5a952991adb3847553d205d1?affid=20180409oschina
6个应当了解的Java比特币开源项目

比特币是第一种被广泛认可并获得众多支持的数字加密货币,如果你考虑在自己的Java系统中增加对比特币的支持,那么相信下面这6个使用Java开发的比特币开源项目会对你所帮助: 1、bitcoinj 代码...

汇智网教程
10/04
0
0
6个你应当了解的Java比特币项目

比特币是第一种被广泛认可并获得众多支持的数字加密货币,如果你考虑 在自己的Java系统中增加对比特币的支持,那么相信下面这6个使用Java开发 的比特币开源项目,会对你有很大的帮助。 1、b...

编程狂魔
10/08
0
0
Java如何离线生成比特币地址

如果你希望在自己的桌面Java应用或者手机安卓应用中集成对比特币 支付的支持,例如,离线生成比特币私钥和地址、接收比特币支付、多重签名转账、 查询钱包余额等,那么使用bitcoinj这个超高人...

编程狂魔
10/08
0
0
使用比特币RPC客户端创建比特币java应用程序

你可以使用RPC客户端在Java中创建有扩展性的比特币应用程序。在这篇博客中,我们将使用JavaBitcoindRpcClient。 在我们开始编码之前,请确保在本地系统中运行比特币核心。如果你没有比特币核...

geek12345
10/09
0
0
iOS和Android比特币开发3个最受欢迎的应用SDK(示例)

如今的比特币不仅是加密货币还是数字支付系统。实际上,由于其独特的功能,比特币已成为投资,储蓄甚至赚取更多钱的真正工具。在本文中,我们想谈谈3个最受欢迎的比特币应用SDK,它可以帮助您...

笔阁
10/17
0
3

没有更多内容

加载失败,请刷新页面

加载更多

《孩子,你慢慢来》的读书笔记与读后感2600字

《孩子,你慢慢来》的读书笔记与读后感2600字: 龙——保护儿童的思维: 今天读《孩子,你慢慢来》龙这一节,安安的妈妈是中国人,她在安安两岁的时候就认识到安安有着固执的个性。安安正是处...

原创小博客
12分钟前
2
0
kubernetes每个节点创建一个服务的Pod

1. 问题场景 希望一个worker节点上仅部署同样的服务一个. 比如: kubernets有三个worker节点,三个节点部署N个副本的api服务, 为了提高服务效率希望加入缓存,需要为三个节点个部署一个redis服务...

jimmywa
16分钟前
4
0
搭建Git服务器

Windows平台下搭建Git服务器 1、在自己电脑搭建Git服务器,且只有自己的电脑能访问。 即使是自己一个人在开发代码也强烈建议使用Git来管理代码。当然也可以只使用本地Git仓库的形式来管理代码...

国仔饼
31分钟前
1
0
百万并发下的Nginx优化,看这一篇就够了!

本文作者主要分享在 Nginx 性能方面的实践经验,希望能给大家带来一些系统化思考,帮助大家更有效地去做 Nginx。 优化方法论 我重点分享如下两个问题: 保持并发连接数,怎么样做到内存有效使...

JackFace
33分钟前
3
0
java_集合

非并发集合 并发集合

grace_233
43分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部