Java实现一个简易的区块链(一)

本文介绍了如何使用Java实现一个简易的区块链,包括哈希值的获取和单链表数据结构的应用。提供了部分基于数组集合的实现代码,但未包含工作量证明机制。参考了B站上的相关视频教程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

- 下面是获得sha256加密后的64位16进制哈希值的类及方法,这里需要先导入一个通用的编码解码包commons-codec依赖,并下载好该资源。

 <!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
    <dependency>
      <groupId>commons-codec</groupId>
      <artifactId>commons-codec</artifactId>
      <version>1.14</version>
    </dependency>


import java.nio.charset.StandardCharsets;
import org.apache.commons.codec.binary.Hex;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * @Auther:刘兰斌
 * @Date: 2021/05/31/9:07
 * @Explain:
 */
public class GetSHA256Str {
    public static void main(String[] args) {
        String t = "luotuo1";//刘兰斌
        String s = getsha256str(t);
        System.out.println(s);
    }
    public static String getsha256str(String string){
        String encoderes="";
        try {//初始化
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            byte[] hash = messageDigest.digest(string.getBytes(StandardCharsets.UTF_8));
            encoderes = Hex.encodeHexString(hash);


        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return encoderes;
    }
}

- 借助单链表的数据结构实现,也可以借助数组集合实现

/**
 * @Auther:刘兰斌
 * @Date: 2021/05/31/20:33
 * @Explain:
 */
public class Blocks {
    private String data;
    private String prehash;
    private String curhash;
    private Blocks next;
    private int nonce;

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public String getPrehash() {
        return prehash;
    }

    public void setPrehash(String prehash) {
        this.prehash = prehash;
    }

    public String getCurhash() {
        return curhash;
    }

    public void setCurhash(String curhash) {
        this.curhash = curhash;
    }

    public Blocks getNext() {
        return next;
    }

    public void setNext(Blocks next) {
        this.next = next;
    }

    public Blocks(String data, String prehash, String curhash, Blocks next) {
        this.data = data;
        this.prehash = prehash;
        this.curhash = computerHash();
        this.next = next;
        this.nonce=1;
    }
    public String computerHash(){
        return GetSHA256Str.getsha256str(this.data+this.prehash+this.nonce);
    }
    //获取难度值
    public String getDificult(int dificulnum){
        String res="";
        for (int i=0;i<dificulnum;i++){
            res+="0";
        }
        return res;
    }
    //开始挖矿
    public void mine(int dificulnum){
        while(true){
            this.curhash=this.computerHash();
        if (!this.curhash.substring(0,dificulnum).equals(this.getDificult(dificulnum))){
                nonce++;
                this.curhash=this.computerHash();
           }else {
            break;
        }
        }
        System.out.println("挖矿结束!"+this.curhash);
    }

    @Override
    public String toString() {
        return "Blocks{" +
                "data='" + data + '\'' +
                ", prehash='" + prehash + '\'' +
                ", curhash='" + curhash + '\'' +
                ", next=" + next +
                '}';
    }
    public static void main(String[] args) {
        Blocks block1 = new Blocks("转账十元","其实我是十元","",null);//这里的前一个区块的hash值实际上是模拟
        Blocks block2 = new Blocks("转账二十元","其实我是二十元","",null);//这里简化只是用来计算curhash
//        System.out.println(block1);
        SingleLinkList singleLinkList = new SingleLinkList();
        singleLinkList.addNode(block1);
        singleLinkList.addNode(block2);
//        System.out.println(singleLinkList);

//        singleLinkList.getAncestor().getNext().setData("转账1000元!");
//        singleLinkList.getAncestor().getNext().setCurhash(
//                singleLinkList.getAncestor().getNext().computerHash());
//
//        boolean validate = singleLinkList.isValidate();//data = "转账1000";
//        System.out.println(validate);
    }

}
class SingleLinkList{
    //初始化第一个结点
    private Blocks ancestor;
    //引入工作量证明机制
    private int dificultnum;

    public Blocks getAncestor() {
        return ancestor;
    }

    public void setAncestor(Blocks ancestor) {
        this.ancestor = ancestor;

    }

    public SingleLinkList() {
        this.ancestor = new Blocks("祖先节点","","",null);
        this.dificultnum = 5;
    }

    @Override
    public String toString() {
        return "SingleLinkList{" +
                "ancestor=" + ancestor +
                '}';
    }

    //添加节点到区块链上中
    public void addNode(Blocks blocks){
        //找到上一个区块的hash值作为添加区块的前一个哈希值
        Blocks temp = ancestor;
        while(true){
            if(temp.getNext()==null){
                break;
            }
            temp = temp.getNext();
        }
        temp.setNext(blocks);
        blocks.setPrehash(temp.getCurhash());
     //   blocks.setCurhash(blocks.computerHash());
        blocks.mine(dificultnum);
        blocks.setNext(null);
    }
//    验证数据合法性
    //验证数据是否合法
    //验证hash是否正确
    public boolean isValidate() {
        //如果为初始化链,肯定合法

        if (ancestor.getNext()==null) {//chain.size() == 1
            //    if(chain.get(0).getOwnhash() != chain.get(0).computerhash()){
            if (!ancestor.getCurhash().equals(ancestor.computerHash())) {
                //!chain.get(0).getOwnhash().equals(chain.get(0).computerhash())
                return false;
            }
            return true;
        }
        //验证完第一个数据后,开始验证后面的数据
        while(ancestor.getNext() != null){
            Blocks nextblocks = ancestor.getNext();
            if (!nextblocks.getCurhash().equals(nextblocks.computerHash())) {
                System.out.println("数据发生篡改!");
                return false;
            }

            //验证此区块的的前哈希值是否等于前一个区块的哈希值
            Blocks preblocks = ancestor;
            if (!nextblocks.getPrehash().equals(preblocks.getCurhash())) {
                System.out.println("失败,前后数据块断裂!");
                return false;
            }
            ancestor=ancestor.getNext();
        }
        return true;
    }

}

  • 附带数组集合实现的部分代码(未引入工作量证明机制)
import java.util.ArrayList;


/**
 * @Auther:刘兰斌
 * @Date: 2021/05/31/9:30
 * @Explain:
 */
public class Block {
    private String data;
    private String prehash;
    private String ownhash;

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    public String getPrehash() {
        return prehash;
    }

    public void setPrehash(String prehash) {
        this.prehash = prehash;
    }

    public String getOwnhash() {
        return ownhash;
    }

    public void setOwnhash(String ownhash) {
        this.ownhash = ownhash;
    }

    public Block(String data, String prehash, String ownhash) {
        this.data = data;
        this.prehash = prehash;
        this.ownhash = computerhash();
    }


    public String computerhash() {
        return GetSHA256Str.getsha256str(this.data + this.prehash);
    }

    @Override
    public String toString() {
        return "Block{" +
                "data='" + data + '\'' +
                ", prehash='" + prehash + '\'' +
                ", ownhash='" + ownhash + '\'' +
                '}';
    }


    public static void main(String[] args) {
        Chain chain = new Chain();
        Block Block = new Block("转账十元", "123", "");
        Block block2 = new Block("转账5元", "", "");
        chain.addBlocktochain(Block);
        chain.addBlocktochain(block2);
        System.out.println(chain);
        //尝试篡改数据
        chain.chain.get(1).data = "转账1000";
        //尝试篡改前后的hash值
        chain.chain.get(1).setOwnhash(chain.chain.get(1).computerhash());
        boolean res = chain.isValidate();
        System.out.println(res);
    }
}

class Chain {
//    Block generater = new Block("祖先节点", "", "");//祖先区块
    ArrayList<Block> chain = new ArrayList<>();

    public Chain() {
        chain.add(new Block("祖先节点", "", ""));
    }

    @Override
    public String toString() {
        return "Chain{" +
                "generater=" + new Block("祖先节点", "", "") +
                ", chain=" + chain +
                '}';
    }

    //添加一个区块到链上
    public ArrayList<Block> addBlocktochain(Block block) {
        //找到上一个区块的hash
        String lasthash = chain.get(chain.size() - 1).getOwnhash();
        block.setPrehash(lasthash);
        block.setOwnhash(block.computerhash());
        chain.add(block);
        return chain;
    }

    //验证数据是否合法
    //验证hash是否正确
    public boolean isValidate() {
        //如果为初始化链,肯定合法
        if (chain.size() == 1) {
            //    if(chain.get(0).getOwnhash() != chain.get(0).computerhash()){
            if (!chain.get(0).getOwnhash().equals(chain.get(0).computerhash())) {
                return false;
            }
            return true;
        }
        //验证完第一个数据后,开始验证后面的数据
        for (int i = 1; i < chain.size(); i++) {
            Block block = chain.get(i);

            if (!block.getOwnhash().equals(block.computerhash())) {
                System.out.println("数据发生篡改!");
                return false;
            }

            //验证此区块的的前哈希值是否等于前一个区块的哈希值
            Block preblock = chain.get(i - 1);
            if (!block.getPrehash().equals(preblock.getOwnhash())) {
                System.out.println("失败,前后数据块断裂!");
                return false;
            }
        }
        return true;
    }

}

参考资源

https://www.bilibili.com/video/BV1CJ411e79V/?spm_id_from=333.788.recommend_more_video.0

https://www.bilibili.com/video/BV1JJ411477R

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值