區塊鏈學習(2) 計算區塊的哈希值

本文的目的:根據一個區塊的信息算出他的哈希值


區塊信息:
https://www.blockchain.com/zh/btc/block-height/20000


區塊頭格式:
共80個字節,上圖中都是字符串,需要轉換爲二進制的區塊頭格式。

字段 大小 描述
version 04字節 版本號
previous block hash 32字節 前一個區塊的哈希
merkle root 32字節 該區塊中交易的merkle樹根的哈希值
time 04字節 該區塊的創建時間戳 utc時間
bits 04字節 該區塊鏈工作量證明難度目標
nonce 04字節 用於證明工作量的計算隨機數

程序思路
1、通過區塊鏈瀏覽器提供的api,獲取一個區塊的信息。
      這裏使用btc.com,以btc的創世塊爲例。

curl -s https://chain.api.btc.com/v3/block/0
{
	"data": {
		"height": 0,
		"version": 1,
		"mrkl_root": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
		"timestamp": 1231006505,
		"bits": 486604799,
		"nonce": 2083236893,
		"hash": "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
		"prev_block_hash": "0000000000000000000000000000000000000000000000000000000000000000",
		"next_block_hash": "00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048",
		"size": 285,
		"pool_difficulty": 2536,
		"difficulty": 1,
		"tx_count": 1,
		"reward_block": 5000000000,
		"reward_fees": 0,
		"created_at": 1488909332,
		"confirmations": 552468,
		"is_orphan": false,
		"curr_max_timestamp": 1231006505,
		"is_sw_block": false,
		"stripped_size": 285,
		"weight": 1140,
		"extras": {
			"pool_name": "unknown",
			"pool_link": ""
		}
	},
	"err_no": 0,
	"err_msg": null
}

2、解析出區塊的頭部信息,生成結果block_header_t,注意各種字節序的轉換。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
          block:0
        version:1
prev_block_hash:0000000000000000000000000000000000000000000000000000000000000000
      mrkl_root:3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a
      timestamp:1231006505
           bits:486604799
          nonce:2083236893
           hash:000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

3、系統的字節序爲小端,80個字節的區塊頭部信息如下:

0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c

4、對區塊頭部進行2次哈希得到最終結果。

sha256-1=af42031e805ff493a07341e2f74ff58149d22ab9ba19f61343e2c86c71c5d66d
sha256-2=000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f

完整的代碼

// xmain.c
// by maxzero

#include "xutils.h"
#include "xsha256.h"

typedef struct _block_header {
    uint32_t ver;
    uint32_t hash_prev[8];
    uint32_t hash_mkrt[8];
    uint32_t timex;
    uint32_t bits ;
    uint32_t nonce;
}block_header_t;

static int make_block_header(block_header_t *block_header, int block_num)
{
    FILE* f = NULL;
    int   n = 0;
    int   r = 0;

    char  url[1024];
    char* buf = NULL;
    int   len = 1*1024*1024*sizeof(char);;
    char  temp[128];

    memset(url, 0x00, sizeof(url));
    sprintf(url, "curl -s https://chain.api.btc.com/v3/block/%d", block_num);
    f = popen(url, "r");

    buf = (char*)malloc(len);
    if (NULL == buf) {
        xprint_err("malloc() failed. len=%d\n", len);
        pclose(f);
        return -1;
    }

    memset(buf, 0x00, len);
    n = fread(buf, 1, len, f);
    if (n <= 0) {
        xprint_err("fread() failed. n=%d\n", n);
        goto xexit;
    }

    printf("n=%d l=%d\n", n, len);
    printf("%s\n\n", buf);

    memset(temp, 0x00, sizeof(temp));
    if (-1 == xkey_value_parser(buf, "\"version\":", ",", temp, sizeof(temp))) {
        r = -1;
        goto xexit;
    }
    else {
        block_header->ver = atoi(temp);
    }

    memset(temp, 0x00, sizeof(temp));
    if (-1 == xkey_value_parser(buf, "\"mrkl_root\":\"", "\",", temp, sizeof(temp))) {
        r = -1;
        goto xexit;
    }
    else {
        hex2bin((uint8_t*)block_header->hash_mkrt, temp, strlen(temp));
        xreverse_dword((uint32_t*)block_header->hash_mkrt, 8, 1);
    }

    memset(temp, 0x00, sizeof(temp));
    if (-1 == xkey_value_parser(buf, "\"timestamp\":", ",", temp, sizeof(temp))) {
        r = -1;
        goto xexit;
    }
    else {
        block_header->timex = atoi(temp);
    }

    memset(temp, 0x00, sizeof(temp));
    if (-1 == xkey_value_parser(buf, "\"bits\":", ",", temp, sizeof(temp))) {
        r = -1;
        goto xexit;
    }
    else {
        block_header->bits = atoi(temp);
    }

    memset(temp, 0x00, sizeof(temp));
    if (-1 == xkey_value_parser(buf, "\"nonce\":", ",", temp, sizeof(temp))) {
        r = -1;
        goto xexit;
    }
    else {
        block_header->nonce = atoi(temp);
    }

    memset(temp, 0x00, sizeof(temp));
    if (-1 == xkey_value_parser(buf, "\"prev_block_hash\":\"", "\",", temp, sizeof(temp))) {
        r = -1;
        goto xexit;
    }
    else {
        hex2bin((uint8_t*)block_header->hash_prev, temp, strlen(temp));
        xreverse_dword((uint32_t*)block_header->hash_prev, 8, 1);
    }

    memset(temp, 0x00, sizeof(temp));
    if (-1 == xkey_value_parser(buf, "\"hash\":\"", "\",", temp, sizeof(temp))) {
        r = -1;
        goto xexit;
    }

    printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
    printf("          block:%u\n", block_num);
    printf("        version:%u\n", block_header->ver);
    printf("prev_block_hash:");    xdump_byte((uint8_t*)block_header->hash_prev, 32, 32, 0);
    printf("      mrkl_root:");    xdump_byte((uint8_t*)block_header->hash_mkrt, 32, 32, 0);
    printf("      timestamp:%u\n", block_header->timex);
    printf("           bits:%u\n", block_header->bits);
    printf("          nonce:%u\n", block_header->nonce);
    printf("           hash:%s\n", temp);
    printf("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n");
    printf("\n");

xexit:
    free(buf);
    pclose(f);
    return r;
}

int hash_block_header(int block_num)
{
    block_header_t block_header;
    uint32_t sha1[8];
    uint32_t sha2[8];
    int i = 0;

    memset(&block_header, 0x00, sizeof(block_header));
    if (0 != make_block_header(&block_header, block_num)) {
        return -1;
    }

    xdump_byte((uint8_t*)&block_header, 80, 80, 0);
    xsha256((uint8_t*)&block_header, 80, sha1);
    printf("sha256-1=");
    for (i=0; i<8; i++) {
        printf("%08x", sha1[i]);
        sha1[i] = htonl(sha1[i]);
    }
    printf("\n");

    xsha256((uint8_t*)sha1, sizeof(sha1), sha2);
    xreverse_dword(sha2, 8, 1);
    printf("sha256-2=");
    for (i=0; i<8; i++) {
        printf("%08x", sha2[i]);
    }
    printf("\n");
    printf("\n");
    return 0;
}

int main(int argc, char* argv[])
{
    int block_num = 0;
    
    if (argc != 2) {
        printf("usage: a.out [block number]\n");
        printf("   ex: a.out 100\n");
        return -1;
    }

    block_num = atoi(argv[1]);
    hash_block_header(block_num);
    return 0;
}

// xsha256.h
// by maxzero

#ifndef _M_XSHA256_H
#define _M_XSHA256_H

#include "xutils.h"

#ifdef  __cplusplus  
extern "C" {  
#endif 

int xsha256(const uint8_t *src, uint32_t len, uint32_t *hash);

#ifdef  __cplusplus  
}
#endif 
#endif

////////////////////////////////////////////////////////////////////////////////

// xsha256.c
// by maxzero

#include "xsha256.h"

#define XSHA_DBG 0
#define SHFR(x, n) (((x) >> (n)))
#define ROTR(x, n) (((x) >> (n)) | ((x) << ((sizeof(x) << 3) - (n))))
#define ROTL(x, n) (((x) << (n)) | ((x) >> ((sizeof(x) << 3) - (n))))

#define CHX(x, y, z) (((x) &  (y)) ^ (~(x) & (z)))
#define MAJ(x, y, z) (((x) &  (y)) ^ ( (x) & (z)) ^ ((y) & (z)))

#define BSIG0(x) (ROTR(x,  2) ^ ROTR(x, 13) ^ ROTR(x, 22))
#define BSIG1(x) (ROTR(x,  6) ^ ROTR(x, 11) ^ ROTR(x, 25))
#define SSIG0(x) (ROTR(x,  7) ^ ROTR(x, 18) ^ SHFR(x,  3))
#define SSIG1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))

#define SHA256_BLOCK_SIZE (512/8)
#define SHA256_COVER_SIZE (SHA256_BLOCK_SIZE*2)


static uint32_t k[64] = {
    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};


static int xtransform(const uint8_t *msg, uint32_t *h)
{
    uint32_t w[64];
    uint32_t a0, b1, c2, d3, e4, f5, g6, h7;
    uint32_t t1, t2;

    int i = 0;
    int j = 0;

    for (i=0; i<16; i++) {
        w[i] = msg[j]<<24 | msg[j+1]<<16 | msg[j+2]<<8 | msg[j+3];
        j += 4;
    }

    for(i=16; i<64; i++){
        w[i] = SSIG1(w[i-2])+w[i-7]+SSIG0(w[i-15])+w[i-16];
    }

#if XSHA_DBG
    xdump_byte((uint8_t*)w, 64*4, 32);
#endif

    a0 = h[0];
    b1 = h[1];
    c2 = h[2];
    d3 = h[3];
    e4 = h[4];
    f5 = h[5];
    g6 = h[6];
    h7 = h[7];

    for (i= 0; i<64; i++) {
        t1 = h7 + BSIG1(e4) + CHX(e4, f5, g6) + k[i] + w[i];
        t2 = BSIG0(a0) + MAJ(a0, b1, c2);

        h7 = g6;
        g6 = f5;
        f5 = e4;
        e4 = d3 + t1;
        d3 = c2;
        c2 = b1;
        b1 = a0;
        a0 = t1 + t2;
    }

    h[0] += a0;
    h[1] += b1;
    h[2] += c2;
    h[3] += d3;
    h[4] += e4;
    h[5] += f5;
    h[6] += g6;
    h[7] += h7;

    return 0;
}

int xsha256(const uint8_t *src, uint32_t len, uint32_t *hash)
{
    uint8_t *tmp = (uint8_t*)src;
    uint8_t  cover_data[SHA256_COVER_SIZE];
    uint32_t cover_size = 0;
    
    uint32_t i = 0;
    uint32_t n = 0;
    uint32_t m = 0;
    uint32_t h[8];

    h[0] = 0x6a09e667;
    h[1] = 0xbb67ae85;
    h[2] = 0x3c6ef372;
    h[3] = 0xa54ff53a;
    h[4] = 0x510e527f;
    h[5] = 0x9b05688c;
    h[6] = 0x1f83d9ab;
    h[7] = 0x5be0cd19;

    memset(cover_data, 0x00, sizeof(uint8_t)*SHA256_COVER_SIZE);

    n = len / SHA256_BLOCK_SIZE;
    m = len % SHA256_BLOCK_SIZE;

    if (m < 56 ) {
        cover_size = SHA256_BLOCK_SIZE;
    }else {
        cover_size = SHA256_BLOCK_SIZE*2;
        
    }

    if (m !=0) {
        memcpy(cover_data, tmp + (n * SHA256_BLOCK_SIZE), m);
    }
    cover_data[m] = 0x80;
    cover_data[cover_size-4]  = ((len*8)&0xff000000) >> 24;
    cover_data[cover_size-3]  = ((len*8)&0x00ff0000) >> 16;
    cover_data[cover_size-2]  = ((len*8)&0x0000ff00) >> 8;
    cover_data[cover_size-1]  = ((len*8)&0x000000ff);

#if XSHA_DBG
    xdump_hex(tmp, len-m, 32);
    xdump_hex(cover_data, cover_size, 32);
#endif

    for (i=0; i<n; i++) {
        xtransform(tmp, h);
        tmp += SHA256_BLOCK_SIZE;
    }

    tmp = cover_data;
    n = cover_size / SHA256_BLOCK_SIZE;
    for (i=0; i<n; i++) {
        xtransform(tmp, h);
        tmp += SHA256_BLOCK_SIZE;
    }
    
    if (NULL != hash) {
        memcpy(hash, h, sizeof(uint32_t)*8);
    }
    return 0;
}

// xutils.h
// by maxzero


#ifndef _M_XUTILS_H
#define _M_XUTILS_H

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <memory.h>
#include <string.h>
#include <time.h>
#include <arpa/inet.h>
#include <stdbool.h>

#ifdef  __cplusplus  
extern "C" {  
#endif 

#define xdbg 1

#if xdbg
#define xprint_log(fmt, ...) \
    printf("[%s:%04d] %s() "      fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)
#define xprint_err(fmt, ...) \
    printf("[%s:%04d] %s() err: " fmt, __FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)
#else
#define xprint_log(fmt, ...)
#define xprint_err(fmt, ...)
#endif

#define XDUMP_LINEN 0x01 
#define XDUMP_SPACE 0x02
#define XDEMP_DEFAULT (XDUMP_SPACE|XDUMP_LINEN)

int xdump_byte(const uint8_t *data, int size, int line, int flag);
uint8_t crc5(uint8_t *data, uint8_t size);
bool hex2bin(unsigned char *binstr, const char *hexstr, size_t len);
void xreverse_byte(unsigned char *s, size_t n);
void xreverse_dword(uint32_t *s, size_t n, int f);
int xkey_value_parser(char *data, char *key, char *end, char *value, int len);

#ifdef  __cplusplus  
}
#endif 

#endif


/////////////////////////////////////////////////////////////////////////////////

// xutils.c
// by maxzero

#include "xutils.h"

static const int hex2bin_tbl[256] = {
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
    -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};

int xdump_byte(const uint8_t *data, int size, int line, int flag)
{
    int i;
    int l = line;
    
    if (size <= 0) { return 0; }

    for (i=0; i<size; i++) {
        if (((i%l)==0) && ((flag&XDUMP_LINEN)==XDUMP_LINEN)) {
            printf( "[%02x] ", i/l );
        }
        printf( "%02x", data[i] );
        if ((flag&XDUMP_SPACE) == XDUMP_SPACE) {
            printf(" ");
        }
        if(((i+1)%l) == 0) {
            printf( "\n" );
        }
    }

    if (size%line != 0) { printf("\n"); }
    return 0;
}

uint8_t crc5(uint8_t *data, uint8_t size)
{
    uint8_t i, j, k;
    uint8_t crc = 0x1f;
    uint8_t crcin [5] = {1, 1, 1, 1, 1};
    uint8_t crcout[5] = {1, 1, 1, 1, 1};
    uint8_t din = 0;

    j = 0x80;
    k = 0;
    for (i=0; i<size; i++) {
        if (*data & j) {
            din = 1;
        } else {
            din = 0;
        }
        crcout[0] = crcin[4] ^ din;
        crcout[1] = crcin[0];
        crcout[2] = crcin[1] ^ crcin[4] ^ din;
        crcout[3] = crcin[2];
        crcout[4] = crcin[3];

        j = j >> 1;
        k++;
        if (k == 8) {
            j = 0x80;
            k = 0;
            data++;
        }
        memcpy(crcin, crcout, 5);
    }

    crc = 0;
    if(crcin[4]) crc |= 0x10;
    if(crcin[3]) crc |= 0x08;
    if(crcin[2]) crc |= 0x04;
    if(crcin[1]) crc |= 0x02;
    if(crcin[0]) crc |= 0x01;
    return crc;
}

bool hex2bin(unsigned char *bin, const char *hexstr, size_t len)
{
    int nibble1, nibble2;
    unsigned char idx;
    bool ret = false;

    while (*hexstr && len) {
        if (!hexstr[1]) {
            xprint_err("hex string truncated.\n");
            return ret;
        }

        idx = *hexstr++;
        nibble1 = hex2bin_tbl[idx];
        idx = *hexstr++;
        nibble2 = hex2bin_tbl[idx];

        if ((nibble1<0) || (nibble2<0)) {
            xprint_err("hex string scan failed.\n");
            return ret;
        }

        *bin++ = (((unsigned char)nibble1)<<4) | ((unsigned char)nibble2);
        --len;
    }

    if (len == 0 && *hexstr == 0) {
        ret = true;
    }

    return ret;
}

void xreverse_byte(unsigned char *s, size_t n)
{
    size_t i = 0;
    size_t j = 0;

    for (i=0, j=n-1; i<j; i++, j--) {
        s[i] = s[i] ^ s[j];
        s[j] = s[j] ^ s[i];
        s[i] = s[i] ^ s[j];
    }
    return ;
}

void xreverse_dword(uint32_t *s, size_t n, int f)
{
    size_t i = 0;
    size_t j = 0;

    for (i=0, j=n-1; i<j; i++, j--) {
        s[i] = s[i] ^ s[j];
        s[j] = s[j] ^ s[i];
        s[i] = s[i] ^ s[j];
        if (1 == f) {
            s[i] = htonl(s[i]);
            s[j] = htonl(s[j]);
        }
    }

    return ;
}

/*解析規則
1、查找關鍵字 key,key不存在返回失敗
2、查找結束符 end  value取值 key到end之間
3、end不存在 嘗試空格當結束符 value取值 key到空格之間
4、空格不存在 value取值 key到data結束
*/
int xkey_value_parser(char *data, char *key, char *end, char *value, int len)
{
    char *a = NULL;
    char *b = NULL; 

    int n = 0;    
    int r = 0;

    a = strstr(data, key);
    if (NULL != a) {
        a += strlen(key);
        b = strstr(a, end);
        if (NULL != b) {
            n = b - a;
            n = (n > len) ? len : n;
            memcpy(value, a, n);
            r = b - data;
        }
        else {
            b = strstr(a, " ");
            if (NULL == b) {
                b = data + strlen(data);
            }
            n = b - a;
            n = (n > len) ? len : n;
            memcpy(value, a, n);
            r = b - data;
        }
    }
    else {
        r = -1;
    }

    if (-1 == r) {
        xprint_err("%s not find. pls check uri\n %s \n", key, data);
    }
    
    return r;
}

編譯運行
ubuntu 14.04 gcc 5.5.0 

[root@ubuntu:src]# gcc xmain.c xsha256.c xutils.c
[root@ubuntu:src]# ./a.out 0

{"data":{"height":0,"version":1,"mrkl_root":"4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b","timestamp":1231006505,"bits":486604799,"nonce":2083236893,"hash":"000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f","prev_block_hash":"0000000000000000000000000000000000000000000000000000000000000000","next_block_hash":"00000000839a8e6886ab5951d76f411475428afc90947ee320161bbf18eb6048","size":285,"pool_difficulty":2536,"difficulty":1,"tx_count":1,"reward_block":5000000000,"reward_fees":0,"created_at":1488909332,"confirmations":553612,"is_orphan":false,"curr_max_timestamp":1231006505,"is_sw_block":false,"stripped_size":285,"weight":1140,"extras":{"pool_name":"unknown","pool_link":""}},"err_no":0,"err_msg":null}

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
          block:0
        version:1
prev_block_hash:0000000000000000000000000000000000000000000000000000000000000000
      mrkl_root:3ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a
      timestamp:1231006505
           bits:486604799
          nonce:2083236893
           hash:000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c
sha256-1=af42031e805ff493a07341e2f74ff58149d22ab9ba19f61343e2c86c71c5d66d
sha256-2=000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章