Blockchain 02

2019-09-26

Proof of Work

내장형시스템 과제로 나온 작업 증명의 간단한 예제를 만들어 보았다.


String bc = "blockchain";

이 프로그램의 목적은 주어진 목표값 이하의 해시를 가지는 논스를 찾는 것이다.

String “blockcahin”과 해시값을 목표값 이하로 만들어주는 nonce로 간이 블록을 구성한다.

class SimpleBlock implements Serializable {
    public String value = "";
    public int nonce = 0;

    public SimpleBlock(String s){
        this.value = s;
    }
}

블록 객체를 생성하기 위한 class SimpleBlock을 byte 형태로 데이터를 변환(직렬화)하기 위해 Serializable를 상속한다.

    public static byte[] getSHA(byte[] input) throws NoSuchAlgorithmException
    {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        return md.digest(input);
    }

    public static byte[] Hash(SimpleBlock sb) throws IOException, NoSuchAlgorithmException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(sb);
        oos.flush();
        byte[] hash = getSHA(bos.toByteArray());
        return hash;
    }

SimpleBlock을 바이트 배열로 변환한 값을 SHA-256 해시값으로 변환하여 바이트 배열로 return한다.

    public static SimpleBlock pow(String bc, int diff) throws IOException, NoSuchAlgorithmException {
        BigInteger difficulty = BigInteger.ONE.shiftLeft(256-diff).add(BigInteger.valueOf(-1));

        SimpleBlock sb = new SimpleBlock(bc);
        while(true){
            BigInteger hash = new BigInteger(1, getSHA(Hash(sb)));
            if(hash.compareTo(difficulty) == -1){
                System.out.println("SHA-256: " + String.format("%64s", hash.toString(16)).replace(' ', '0'));
                return sb;
            }
            else sb.nonce++;
        }
    }

매개변수 String bc는 SimpleBlock 의 value이며, int diff는 작업 난이도이다.

BigInteger difficulty = BigInteger.ONE.shiftLeft(256-diff).add(BigInteger.valueOf(-1));

작업 난이도는 매개변수로 왼쪽 시프트 연산을 조절하며 정해진다.

if(hash.compareTo(difficulty) == -1){
    System.out.println("SHA-256: " + String.format("%64s", hash.toString(16)).replace(' ', '0'));
    return sb;
    }
else sb.nonce++;
}

목표값 이하의 해시를 찾는 데 성공하였다면 결과를 반환하고, 실패하였다면 SimpleBlock의 nonce값을 올려서 다시 시도한다.